/**
* GeoDress - A program for reverse geocoding
* Copyright (C) 2010 Stefan T.
*
* See COPYING for Details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package geodress.model.writer;
import geodress.exceptions.FileTypeNotSupportedException;
import geodress.exceptions.MetaDataErrorException;
import geodress.exceptions.OperationNotSupportedException;
import geodress.main.FileOperations;
import geodress.main.InfoConstants;
import geodress.main.Logging;
import geodress.model.Address;
import geodress.model.Picture;
import geodress.model.PictureFilter;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.ImageWriteException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.SanselanException;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.jpeg.exifRewrite.ExifRewriter;
import org.apache.sanselan.formats.tiff.constants.TagInfo;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.constants.TiffFieldTypeConstants;
import org.apache.sanselan.formats.tiff.write.TiffOutputField;
import org.apache.sanselan.formats.tiff.write.TiffOutputSet;
/**
* A writer for EXIF data (in JPEG files) using <a
* href="http://commons.apache.org/sanselan">Sanselan</a>.
*
* @author Stefan T.
* @deprecated Writing with Sanselan leads to incomplete meta data fields.
*/
@Deprecated
public class SanselanWriter implements MetaDataWriter {
/** Logger object */
private static Logger logger = null;
/** a map with all field values that should be saved */
private Map<TagInfo, String> saveMap;
/* Initializes logger. */
static {
logger = Logging.getLogger(SanselanWriter.class.getName());
}
/**
* Initializes class.
*/
public SanselanWriter() {
saveMap = new HashMap<TagInfo, String>();
}
/**
* @see geodress.model.writer.MetaDataWriter#setData(int, java.lang.String)
*/
@Override
public void setData(int field, String value)
throws OperationNotSupportedException {
switch (field) {
case InfoConstants.GPS_LATITUDE:
throw new OperationNotSupportedException(
"writing latitude is not supported yet");
case InfoConstants.GPS_LONGITUDE:
throw new OperationNotSupportedException(
"writing longitude is not supported yet");
case InfoConstants.DATE_TIME:
throw new OperationNotSupportedException(
"writing date/time is not supported yet");
case InfoConstants.USER_COMMENT:
logger.log(Level.FINER, "new user comment for writing: " + value);
saveMap.put(TiffConstants.EXIF_TAG_USER_COMMENT, value);
break;
case InfoConstants.IMAGE_DESCRIPTION:
logger.log(Level.FINER, "new image description for writing: "
+ value);
saveMap.put(TiffConstants.TIFF_TAG_IMAGE_DESCRIPTION, value);
break;
default:
throw new OperationNotSupportedException("writing for field "
+ field + " is not supported yet");
}
}
/**
* <b>Attention</b>: Fields that already exist will be overwritten!
*
* @see geodress.model.writer.MetaDataWriter#write(File)
*/
@Override
public void write(File file) throws MetaDataErrorException, IOException,
FileTypeNotSupportedException {
/* reject picture if its type is not JPEG */
if (!new PictureFilter().accept(file)) {
throw new FileTypeNotSupportedException("the file type of "
+ file.getAbsolutePath()
+ " is not supported for writing EXIF data");
}
logger
.log(Level.FINE, "writing EXIF data of "
+ file.getAbsolutePath());
/* create the TiffOutputSet with all existing EXIF data */
TiffOutputSet exifTags = new TiffOutputSet();
/* load old JPEG picture and existing EXIF data */
JpegImageMetadata jpegMetadata = null;
try {
jpegMetadata = (JpegImageMetadata) Sanselan.getMetadata(file);
} catch (ImageReadException ire) {
/* do nothing */
logger.log(Level.INFO, "error while preparing meta data writing "
+ "(maybe picture contains no meta data)", ire);
}
/* check whether meta data exist */
if (jpegMetadata != null
&& jpegMetadata.getExif() != null
&& (!(file instanceof geodress.model.Picture) || ((Picture) file)
.getAddress().getStatus() != Address.STATUS_DEFAULT)) {
try {
exifTags = jpegMetadata.getExif().getOutputSet();
} catch (ImageWriteException iwe) {
/* do nothing */
logger.log(Level.INFO,
"error while preparing meta data writing", iwe);
}
/* iterate all fields to save and store them into the TiffOutputSet */
for (TagInfo field : saveMap.keySet()) {
/* remove the field if it already exists */
TiffOutputField metadataField = exifTags.findField(field);
if (metadataField != null) {
exifTags.removeField(field);
}
TiffOutputField outputField = new TiffOutputField(field.tag,
field, TiffFieldTypeConstants.FIELD_TYPE_ASCII, saveMap
.get(field).length(), saveMap.get(field)
.getBytes());
try {
exifTags.getOrCreateExifDirectory().add(outputField);
} catch (ImageWriteException iwe) {
logger.log(Level.WARNING, "error while writing EXIF data",
iwe);
}
}
try {
/* create temporary file */
File tempFile = File.createTempFile("geodress_writing_temp-"
+ System.currentTimeMillis(), ".jpg");
tempFile.deleteOnExit(); // delete file on exit
OutputStream os = new BufferedOutputStream(
new FileOutputStream(tempFile),
FileOperations.BUFFER_SIZE);
/* update EXIF data in temp file */
new ExifRewriter().updateExifMetadataLossless(file, os,
exifTags);
/* move temporary file to original file */
file.delete();
FileOperations.move(tempFile, file.getAbsoluteFile());
} catch (SanselanException se) {
logger.log(Level.WARNING, "error while writing EXIF data to "
+ file.getAbsolutePath(), se);
}
}
/* delete the map after all fields written */
saveMap.clear();
}
/**
* <b>Attention</b>: This method has currently no function!
*
* @see geodress.model.writer.MetaDataWriter#setBackupMode(boolean)
*/
@Override
public void setBackupMode(boolean backup) {
// TODO no function
}
}