我正在尝试从图片中提取日期信息。我相处得很好但我有这个问题困扰了我2天。我甚至一次重写整个代码仍然得到它。
我显然得到了一个NP,因为我在方法grabExifSubIFDDirectory中返回null。这是主要问题,它声称有没有目录可用,而应该有一个。 为什么它不能抓住目录?我正在使用standrd jpegs和其他格式。
将jar放在带有图片的文件夹中。
如果有人能指出(嘿)我的方向?
Package utils:
package utils;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.JOptionPane;
public class FileUtils {
private ArrayList<String> fileNamesList;
public FileUtils(String jarFilePath) {
setFileNames(jarFilePath);
}
// Retrieves a Metadata object from a File object and returns it.
public Metadata grabFileMetaData(String filePath) {
Metadata metadata = null;
File file = new File(filePath);
try {
metadata = ImageMetadataReader.readMetadata(file);
} catch (ImageProcessingException e) {
JOptionPane.showMessageDialog(null, "Error: " + e);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error: " + e);
}
return metadata;
}
// Retrieves a ExifSubIFDDirectory object from a Metadata object and returns it.
public ExifSubIFDDirectory grabExifSubIFDDirectory(Metadata metadata, String filePath) {
ExifSubIFDDirectory directory;
if (metadata.containsDirectory(ExifSubIFDDirectory.class)) {
directory = (ExifSubIFDDirectory) metadata.getDirectory(ExifSubIFDDirectory.class);
return directory;
} else {
JOptionPane.showMessageDialog(null, "File at: " + filePath + " does not contain exif date.");
return null;
}
}
// Retrieves a Date object from a ExifSubIFDDirectory object and returns it.
public Date grabDate(ExifSubIFDDirectory directory) {
Date date;
date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
return date;
}
// Return the actual Date object using the above methods.
public Date getDate(String filePath) {
return grabDate(grabExifSubIFDDirectory(grabFileMetaData(filePath), filePath));
}
// Retrieves the names of the files in the same folder as the executed jar.
// Saves them in a variable.
public void setFileNames(String jarPath) {
ArrayList<String> temp = new ArrayList();
String path = jarPath;
String files;
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (File listOfFile : listOfFiles) {
if (listOfFile.isFile()) {
files = listOfFile.getName();
if (!"PhotoRenamer.jar".equals(files) && !"Thumbs.db".equals(files)) {
temp.add(files);
}
}
}
this.fileNamesList = temp;
}
// getter
public ArrayList<String> getFileNamesList() {
return fileNamesList;
}
}
Package domein:
package domein;
import utils.FileUtils;
import utils.JarUtils;
import java.util.ArrayList;
public class DomeinController {
FileUtils fileUtils;
JarUtils jarUtils;
public DomeinController() {
this.jarUtils = new JarUtils();
this.fileUtils = new FileUtils(jarUtils.getJarPath());
}
public ArrayList<String> getFileNamesList() {
return fileUtils.getFileNamesList();
}
public String getJarPath() {
return jarUtils.getJarPath();
}
// Retrieve string from Date object of the file with the number i.
public String getDate(int i) {
return fileUtils.getDate(createFilePath(i)).toString();
}
public String createFilePath(int i) {
return getJarPath() + "\\" + fileUtils.getFileNamesList().get(i);
}
}
包启动:
package startup;
import domein.DomeinController;
import java.net.URISyntaxException;
import javax.swing.JOptionPane;
public class Main {
public static void main(String[] args) throws URISyntaxException {
DomeinController dc = new DomeinController();
// print out jar path
JOptionPane.showMessageDialog(null,dc.getJarPath());
// print out file names in folder
String lijstje = "";
for (int i=0;i<dc.getFileNamesList().size();i++){
lijstje += dc.getFileNamesList().get(i);
}
JOptionPane.showMessageDialog(null,lijstje);
JOptionPane.showMessageDialog(null,dc.getDate(1));
}
}
答案 0 :(得分:2)
getDate(String filePath)
方法工作正常,我测试了它。
所以它必须来自图片本身
getDate
方法适合您。用来自互联网的图片进行测试。Metadata
不为空,文件确实存在,因此图片没有EXIF信息,毫无疑问。答案 1 :(得分:1)
您必须意识到并非所有图像都包含EXIF信息。出于多种原因,可以从图像中清除元数据。
我今天早些时候遇到过类似的问题,这是我的解决方案:
public HashMap<String, String> getMetadata(File photoFile){
Metadata metadata;
ExifSubIFDDirectory exifSubIFDDirectory;
HashMap<String, String> tagMap = new HashMap<>();
try {
metadata = ImageMetadataReader.readMetadata(photoFile);
exifSubIFDDirectory = metadata.getDirectory(ExifSubIFDDirectory.class);
ExifSubIFDDescriptor exifSubIFDDescriptor = new ExifSubIFDDescriptor(exifSubIFDDirectory);
if (exifSubIFDDirectory != null) {
tagMap.put("lens", exifSubIFDDirectory.getDescription(ExifSubIFDDirectory.TAG_LENS_MODEL).toString());
tagMap.put("captureDate", exifSubIFDDirectory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL).toString());
tagMap.put("shutter", exifSubIFDDescriptor.getExposureTimeDescription());
tagMap.put("aperture", exifSubIFDDescriptor.getFNumberDescription());
tagMap.put("focalLength", exifSubIFDDescriptor.getFocalLengthDescription());
tagMap.put("iso", exifSubIFDDescriptor.getIsoEquivalentDescription());
tagMap.put("meterMode", exifSubIFDDescriptor.getMeteringModeDescription());
//null is a possible return value from the method calls above. Replace them
//with default no value string
for (String key : tagMap.keySet()){
if (tagMap.get(key) == null)
tagMap.put(key, "No Value Recorded");
}
} else {
Date currentDate = new Date();
tagMap.put("captureDate", currentDate.toString());
tagMap.put("shutter", "No Value Recorded");
tagMap.put("aperture", "No Value Recorded");
tagMap.put("focalLength", "No Value Recorded");
tagMap.put("iso", "No Value Recorded");
tagMap.put("meterMode","No Value Recorded");
tagMap.put("lens", "No Value Recorded");
}
} catch (ImageProcessingException|IOException|NullPointerException e) {
//unhandled exception, put out logging statement
log.error("Error processing metadata for file " + photoFile.getName() + "\n" + e.getStackTrace());
}
return tagMap;
}
如您所见,我在做任何工作之前检查ExifSubIFDDirectory
对象是否存在。如果是,则我想要的元数据字段保存在HashMap对象中,该对象稍后会保留在数据库中。如果标记不存在,则将其存储为空值,稍后将替换为“未找到值”字符串。
基本上,您的问题不是检查ExifSubIFDDirectory
对象是否通过metadata.getDirectory
调用初始化。我认为如果您使用带有元数据集的图像,则在测试期间不会遇到此问题。
答案 2 :(得分:1)
(这是来自图像编解码器视角的一般建议。它可能适用于或不适用于Drew Noakes的开源库用户。)
我的第一步是使用Phil Harvey's ExifTool以相当详尽的方式从JPEG文件中转储元数据。
一旦您确定JPEG文件包含EXIF数据,接下来就是为了找出库不返回该部分数据的故障排除工作。它可能正确地解析它,但也许你的代码没有按照预期的方式从它的API中检索它。
(由于我不知道这个开源库,我不能提供任何特定于此库的建议。)
检查JPEG文件是否包含APP1段。 APP1段由两个字节的序列0xFF 0xE1
标记。
不同的图像库提供了查找APP1段是否存在的不同方法。其他库可能会从API用户跳过,忽略或使用和隐藏此段。
如果您的库允许,请为APP1安装元数据头事件处理程序,以便您可以查看对其数据执行的处理。然后,您可以跟踪库打算如何存储并通过其API提供该数据。
http://www.digitalpreservation.gov/formats/fdd/fdd000147.shtml