Android 如何修复JPG文件中的exif警告和问题?
我写了自己的相机应用程序。此应用程序在jpg文件中写入exif信息。它工作得很好,但exifInferface类存在一些问题,例如,我在重新读取JPG文件时遇到以下错误:Android 如何修复JPG文件中的exif警告和问题?,android,exif,Android,Exif,我写了自己的相机应用程序。此应用程序在jpg文件中写入exif信息。它工作得很好,但exifInferface类存在一些问题,例如,我在重新读取JPG文件时遇到以下错误: Warning Invalid EXIF text encoding Warning Invalid size (8589934590) for IFD0 tag 0x8827 Warning Bad IFD1 directory 我知道exif信息的IFD0指针已断开。可能是在写入exif信息时指针断开了 然而,我在
Warning Invalid EXIF text encoding
Warning Invalid size (8589934590) for IFD0 tag 0x8827
Warning Bad IFD1 directory
我知道exif信息的IFD0指针已断开。可能是在写入exif信息时指针断开了
然而,我在谷歌上搜索了一下,什么也没找到
我使用这个类来读写exif信息:
public class ExifHelper {
private String aperature = null;
private String exposureTime = null;
private String flash = null;
private String focalLength = null;
private String gpsAltitude = null;
private String gpsAltitudeRef = null;
private String gpsDateStamp = null;
private String gpsLatitude = null;
private String gpsLatitudeRef = null;
private String gpsLongitude = null;
private String gpsLongitudeRef = null;
private String gpsProcessingMethod = null;
private String gpsTimestamp = null;
private String iso = null;
private String make = null;
private String model = null;
private String imageLength = null;
private String imageWidth = null;
private String orientation = null;
private String whiteBalance = null;
private String exifVersion = null;
private String time = null;
private ExifInterface inFile = null;
private ExifInterface outFile = null;
final static String TAG = "ExifHelper";
/**
* The file before it is compressed
*
* @param filePath
* @throws IOException
*/
public void createInFile(String filePath) throws IOException {
this.inFile = new ExifInterface(filePath);
}
/**
* The file after it has been compressed
*
* @param filePath
* @throws IOException
*/
public void createOutFile(String filePath) throws IOException {
this.outFile = new ExifInterface(filePath);
}
/**
* Reads all the EXIF data from the input file.
*/
public void readExifData() {
this.aperature = inFile.getAttribute(ExifInterface.TAG_APERTURE);
this.exposureTime = inFile.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
this.flash = inFile.getAttribute(ExifInterface.TAG_FLASH);
this.focalLength = inFile.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
this.gpsAltitude = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE);
this.gpsAltitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF);
this.gpsDateStamp = inFile.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
this.gpsLatitude = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
this.gpsLatitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
this.gpsLongitude = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
this.gpsLongitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
this.gpsProcessingMethod = inFile.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
this.gpsTimestamp = inFile.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
this.imageLength = inFile.getAttribute(ExifInterface.TAG_IMAGE_LENGTH);
this.imageWidth = inFile.getAttribute(ExifInterface.TAG_IMAGE_WIDTH);
this.iso = inFile.getAttribute(ExifInterface.TAG_ISO);
this.make = inFile.getAttribute(ExifInterface.TAG_MAKE);
this.model = inFile.getAttribute(ExifInterface.TAG_MODEL);
this.orientation = inFile.getAttribute(ExifInterface.TAG_ORIENTATION);
this.whiteBalance = inFile.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
this.exifVersion = inFile.getAttribute("ExifVersion");
}
/**
* Writes the previously stored EXIF data to the output file.
* @param pictureDate
* @param orientationValues
* @param accelValues
*
* @throws IOException
*/
public void writeExifData(String pictureDate) throws IOException {
// Don't try to write to a null file
if (this.outFile == null) {
return;
}
if (this.aperature != null) {
this.outFile.setAttribute(ExifInterface.TAG_APERTURE, this.aperature);
}
if (this.exposureTime != null) {
this.outFile.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, this.exposureTime);
}
if (this.flash != null) {
this.outFile.setAttribute(ExifInterface.TAG_FLASH, this.flash);
}
if (this.focalLength != null) {
this.outFile.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, this.focalLength);
}
if (this.gpsAltitude != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, this.gpsAltitude);
}
if (this.gpsAltitudeRef != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, this.gpsAltitudeRef);
}
if (this.gpsDateStamp != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, this.gpsDateStamp);
}
if (this.gpsLatitude != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE, this.gpsLatitude);
}
if (this.gpsLatitudeRef != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, this.gpsLatitudeRef);
}
if (this.gpsLongitude != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, this.gpsLongitude);
}
if (this.gpsLongitudeRef != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, this.gpsLongitudeRef);
}
if (this.gpsProcessingMethod != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, this.gpsProcessingMethod);
}
if (this.gpsTimestamp != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, this.gpsTimestamp);
}
if (this.iso != null) {
this.outFile.setAttribute(ExifInterface.TAG_ISO, this.iso);
}
if (this.make != null) {
this.outFile.setAttribute(ExifInterface.TAG_MAKE, this.make);
}
if (this.model != null) {
this.outFile.setAttribute(ExifInterface.TAG_MODEL, this.model);
}
if (this.orientation != null) {
this.outFile.setAttribute(ExifInterface.TAG_ORIENTATION, this.orientation);
}
if (this.whiteBalance != null) {
this.outFile.setAttribute(ExifInterface.TAG_WHITE_BALANCE, this.whiteBalance);
}
if (this.exifVersion != null) {
this.outFile.setAttribute("ExifVersion", this.exifVersion);
}
this.outFile.setAttribute(ExifInterface.TAG_IMAGE_LENGTH, this.imageLength);
this.outFile.setAttribute(ExifInterface.TAG_IMAGE_WIDTH, this.imageWidth);
this.outFile.setAttribute(ExifInterface.TAG_DATETIME, pictureDate);
String mString = exifRandomZahlen();
this.outFile.setAttribute("UserComment", mString);
this.outFile.saveAttributes();
}
我还写了两张照片,形成了拍摄方法。一个是原来没有问题,第二个是修改exif信息。我认为,通过将ExiFinInterface写回JPG,它存在问题
我使用DumpImage工具查看exif信息。此工具来自元工作组www.metadataworkinggroup.org
所以我有一个大问题,如何修复这个损坏的exif数据?例如,IDF0指针
有人知道或有同样的问题吗
例如,我在exif信息中两次获得Tag_DATETIME
这是用于保存照片的类:
public class Photo extends Activity implements PictureCallback {
public interface OnPictureTakenListener {
void pictureTaken(File pictureFile, File pictureFilePatched, String exifDateString);
}
private final Context context;
private OnPictureTakenListener listener;
public Photo(Context ourContext, OnPictureTakenListener theListener) {
this.context = ourContext;
this.listener = theListener;
}
@SuppressLint("SimpleDateFormat")
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Date date = new Date();
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs())
{
Log.d(AndroidCamera.DEBUG_TAG,
"Can't create directory to save image.");
Toast.makeText(context, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
SimpleDateFormat dateConverter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
String exifDateString = dateFormat.format(date);
String datePicture = dateConverter.format(date);
String photoFile = "Picture_" + datePicture + ".jpg";
String photoFilePatched = "Picture_" + datePicture + "_patched.jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
String filenamePatched = pictureFileDir.getPath() + File.separator + photoFilePatched;
File pictureFile = new File(filename);
File pictureFilePatched = new File (filenamePatched);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
FileOutputStream fosPatched = new FileOutputStream(pictureFilePatched);
fos.write(data);
fosPatched.write(data);
fos.close();
fosPatched.close();
Toast.makeText(context, "New Image saved:" + photoFile,
Toast.LENGTH_LONG).show();
} catch (Exception error) {
Log.d(AndroidCamera.DEBUG_TAG, "File" + filename + " not saved: "
+ error.getMessage());
Toast.makeText(context, "Image could not be saved.",
Toast.LENGTH_LONG).show();
}
listener.pictureTaken(pictureFile,pictureFilePatched,exifDateString);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
}
private File getDir() {
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
return new File(sdDir, "Camera");
}
static final int REQUEST_IMAGE_CAPTURE = 1;
}
在这里的主要活动中,我从两张图片中调用一张来编写exif信息:
camera.takePicture(null, null, new Photo(this,
new Photo.OnPictureTakenListener() {
public void pictureTaken(final File pictureFile,final File pictureFilePatched , final String date) {
final String fileName = pictureFile.getPath();
final String fileNamePatched = pictureFilePatched.getPath();
final String dateTime = date;
// don't start picture preview immediately, but a little
// delayed...
continueWithPreview.postDelayed(new Runnable() {
@Override
public void run() {
try {
// EXIF Matadata change
ExifHelper exifHelper = new ExifHelper();
exifHelper.createInFile(fileName);
//EXIF Metadata read
exifHelper.readExifData();
exifHelper.createOutFile(fileNamePatched);
//Exif Metadata write
exifHelper.writeExifData(dateTime);
} catch (IOException e) {
e.printStackTrace();
Log.e("PictureActivity", e.getLocalizedMessage());
}
if (null != camera)
{
camera.startPreview();
Toast.makeText(AndroidCamera.this, "started!",
Toast.LENGTH_SHORT).show();
}
}
}, 2500);
请说明如何在文件上调用此类的函数。还是在两个文件上?我已经更新了我的图片?那是一个应用程序吗?不是在游戏商店。我做了一个活动,把你的ExifHelper放进去,拿了一个jpg文件并复制了一份。然后执行try块中的五条语句。修补后的图像可以显示,但由于我没有应用程序调查exif,我将文件传输到了PC顶部。使用IrfanView查看ExifInfo。原始文件有43个exif标记,修补的只有19个。您正在从一个文件中读取exif信息,然后通过对另一个文件的一些更改将此信息写回。你为什么不从文件本身读取它呢?你有没有做过一个测试,从一个文件中读取exif信息,然后将其原封不动地写回同一个文件?我会再写更多exif标签回来。。。但是ExiFinInterface类不会将其添加到其他类中,因为它会覆盖exif信息。因此,只有exifhelper类中的exif标记才会添加到exif元数据中