import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import com.android.gallery3d.filtershow.pipeline.ProcessingService;
import com.android.gallery3d.util.UsageStatistics;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
return exif;
}
- public boolean putExifData(File file, ExifInterface exif, Bitmap image) {
+ public boolean putExifData(File file, ExifInterface exif, Bitmap image,
+ int jpegCompressQuality) {
boolean ret = false;
+ OutputStream s = null;
try {
- exif.writeExif(image, file.getAbsolutePath());
+ s = exif.getExifWriterStream(file.getAbsolutePath());
+ image.compress(Bitmap.CompressFormat.JPEG,
+ (jpegCompressQuality > 0) ? jpegCompressQuality : 1, s);
+ s.flush();
+ s.close();
+ s = null;
ret = true;
} catch (FileNotFoundException e) {
Log.w(LOGTAG, "File not found: " + file.getAbsolutePath(), e);
} catch (IOException e) {
Log.w(LOGTAG, "Could not write exif: ", e);
+ } finally {
+ Utils.closeSilently(s);
}
return ret;
}
- private Uri resetToOriginalImageIfNeeded(ImagePreset preset) {
+ private Uri resetToOriginalImageIfNeeded(ImagePreset preset, boolean doAuxBackup) {
Uri uri = null;
if (!preset.hasModifications()) {
// This can happen only when preset has no modification but save
if (srcFile != null) {
srcFile.renameTo(mDestinationFile);
uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri,
- mDestinationFile, System.currentTimeMillis());
+ mDestinationFile, System.currentTimeMillis(), doAuxBackup);
}
}
return uri;
}
}
- public Uri processAndSaveImage(ImagePreset preset) {
+ public Uri processAndSaveImage(ImagePreset preset, boolean doAuxBackup,
+ int quality, float sizeFactor) {
- Uri uri = resetToOriginalImageIfNeeded(preset);
+ Uri uri = resetToOriginalImageIfNeeded(preset, doAuxBackup);
if (uri != null) {
return null;
}
// If necessary, move the source file into the auxiliary directory,
// newSourceUri is then pointing to the new location.
// If no file is moved, newSourceUri will be the same as mSourceUri.
- Uri newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile);
+ Uri newSourceUri = mSourceUri;
+ if (doAuxBackup) {
+ newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile);
+ }
// Stopgap fix for low-memory devices.
while (noBitmap) {
if (bitmap == null) {
return null;
}
+ if (sizeFactor != 1f) {
+ // if we have a valid size
+ int w = (int) (bitmap.getWidth() * sizeFactor);
+ int h = (int) (bitmap.getHeight() * sizeFactor);
+ bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
+ }
updateProgress();
CachingPipeline pipeline = new CachingPipeline(FiltersManager.getManager(),
"Saving");
updateProgress();
// If we succeed in writing the bitmap as a jpeg, return a uri.
- if (putExifData(mDestinationFile, exif, bitmap)) {
+ if (putExifData(mDestinationFile, exif, bitmap, quality)) {
putPanoramaXMPData(mDestinationFile, xmp);
// mDestinationFile will save the newSourceUri info in the XMP.
XmpPresets.writeFilterXMP(mContext, newSourceUri,
// After this call, mSelectedImageUri will be actually
// pointing at the new file mDestinationFile.
uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri,
- mDestinationFile, time);
+ mDestinationFile, time, doAuxBackup);
}
updateProgress();
/**
* Move the source file to auxiliary directory if needed and return the Uri
- * pointing to this new source file.
+ * pointing to this new source file. If any file error happens, then just
+ * don't move into the auxiliary directory.
* @param srcUri Uri to the source image.
* @param dstFile Providing the destination file info to help to build the
* auxiliary directory and new source file's name.
// if necessary.
File auxDiretory = getLocalAuxDirectory(dstFile);
if (!auxDiretory.exists()) {
- auxDiretory.mkdirs();
+ boolean success = auxDiretory.mkdirs();
+ if (!success) {
+ return srcUri;
+ }
}
// Make sure there is a .nomedia file in the auxiliary directory, such
// We are using the destination file name such that photos sitting in
// the auxiliary directory are matching the parent directory.
File newSrcFile = new File(auxDiretory, dstFile.getName());
+ // Maintain the suffix during move
+ String to = newSrcFile.getName();
+ String from = srcFile.getName();
+ to = to.substring(to.lastIndexOf("."));
+ from = from.substring(from.lastIndexOf("."));
+
+ if (!to.equals(from)) {
+ String name = dstFile.getName();
+ name = name.substring(0, name.lastIndexOf(".")) + from;
+ newSrcFile = new File(auxDiretory, name);
+ }
if (!newSrcFile.exists()) {
- srcFile.renameTo(newSrcFile);
+ boolean success = srcFile.renameTo(newSrcFile);
+ if (!success) {
+ return srcUri;
+ }
}
return Uri.fromFile(newSrcFile);
String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time));
File saveDirectory = getFinalSaveDirectory(context, sourceUri);
File file = new File(saveDirectory, filename + ".JPG");
- return linkNewFileToUri(context, sourceUri, file, time);
+ return linkNewFileToUri(context, sourceUri, file, time, false);
}
public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity,
Uri sourceImageUri = MasterImage.getImage().getUri();
Intent processIntent = ProcessingService.getSaveIntent(filterShowActivity, preset,
- destination, selectedImageUri, sourceImageUri);
+ destination, selectedImageUri, sourceImageUri, false, 90, 1f);
filterShowActivity.startService(processIntent);
* @return the final Uri referring to the <code>file</code>.
*/
public static Uri linkNewFileToUri(Context context, Uri sourceUri,
- File file, long time) {
+ File file, long time, boolean deleteOriginal) {
File oldSelectedFile = getLocalFileFromUri(context, sourceUri);
final ContentValues values = new ContentValues();
});
Uri result = sourceUri;
- if (oldSelectedFile == null) {
+
+ // In the case of incoming Uri is just a local file Uri (like a cached
+ // file), we can't just update the Uri. We have to create a new Uri.
+ boolean fileUri = isFileUri(sourceUri);
+
+ if (fileUri || oldSelectedFile == null || !deleteOriginal) {
result = context.getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
oldSelectedFile.delete();
}
}
-
return result;
}
+ /**
+ * @param sourceUri
+ * @return true if the sourceUri is a local file Uri.
+ */
+ private static boolean isFileUri(Uri sourceUri) {
+ String scheme = sourceUri.getScheme();
+ if (scheme != null && scheme.equals(ContentResolver.SCHEME_FILE)) {
+ return true;
+ }
+ return false;
+ }
+
}