Loading src/com/android/gallery3d/data/ImageCacheRequest.java +6 −4 Original line number Diff line number Diff line Loading @@ -32,17 +32,19 @@ abstract class ImageCacheRequest implements Job<Bitmap> { private Path mPath; private int mType; private int mTargetSize; private long mTimeModified; public ImageCacheRequest(GalleryApp application, Path path, int type, int targetSize) { Path path, long timeModified, int type, int targetSize) { mApplication = application; mPath = path; mType = type; mTargetSize = targetSize; mTimeModified = timeModified; } private String debugTag() { return mPath + "," + return mPath + "," + mTimeModified + "," + ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" : (mType == MediaItem.TYPE_MICROTHUMBNAIL) ? "MICROTHUMB" : "?"); } Loading @@ -53,7 +55,7 @@ abstract class ImageCacheRequest implements Job<Bitmap> { BytesBuffer buffer = MediaItem.getBytesBufferPool().get(); try { boolean found = cacheService.getImageData(mPath, mType, buffer); boolean found = cacheService.getImageData(mPath, mTimeModified, mType, buffer); if (jc.isCancelled()) return null; if (found) { BitmapFactory.Options options = new BitmapFactory.Options(); Loading Loading @@ -92,7 +94,7 @@ abstract class ImageCacheRequest implements Job<Bitmap> { byte[] array = BitmapUtils.compressToBytes(bitmap); if (jc.isCancelled()) return null; cacheService.putImageData(mPath, mType, array); cacheService.putImageData(mPath, mTimeModified, mType, array); return bitmap; } Loading src/com/android/gallery3d/data/ImageCacheService.java +10 −9 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ public class ImageCacheService { } /** * Gets the cached image data for the given <code>path</code> and <code>type</code>. * Gets the cached image data for the given <code>path</code>, * <code>timeModified</code> and <code>type</code>. * * The image data will be stored in <code>buffer.data</code>, started from * <code>buffer.offset</code> for <code>buffer.length</code> bytes. If the Loading @@ -54,8 +55,8 @@ public class ImageCacheService { * * @return true if the image data is found; false if not found. */ public boolean getImageData(Path path, int type, BytesBuffer buffer) { byte[] key = makeKey(path, type); public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) { byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); try { LookupRequest request = new LookupRequest(); Loading @@ -76,8 +77,8 @@ public class ImageCacheService { return false; } public void putImageData(Path path, int type, byte[] value) { byte[] key = makeKey(path, type); public void putImageData(Path path, long timeModified, int type, byte[] value) { byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); buffer.put(key); Loading @@ -91,8 +92,8 @@ public class ImageCacheService { } } public void clearImageData(Path path, int type) { byte[] key = makeKey(path, type); public void clearImageData(Path path, long timeModified, int type) { byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); synchronized (mCache) { try { Loading @@ -103,8 +104,8 @@ public class ImageCacheService { } } private static byte[] makeKey(Path path, int type) { return GalleryUtils.getBytes(path.toString() + "+" + type); private static byte[] makeKey(Path path, long timeModified, int type) { return GalleryUtils.getBytes(path.toString() + "+" + timeModified + "+" + type); } private static boolean isSameKey(byte[] key, byte[] buffer) { Loading src/com/android/gallery3d/data/LocalImage.java +6 −4 Original line number Diff line number Diff line Loading @@ -173,15 +173,17 @@ public class LocalImage extends LocalMediaItem { @Override public Job<Bitmap> requestImage(int type) { return new LocalImageRequest(mApplication, mPath, type, filePath); return new LocalImageRequest(mApplication, mPath, dateModifiedInSec, type, filePath); } public static class LocalImageRequest extends ImageCacheRequest { private String mLocalFilePath; LocalImageRequest(GalleryApp application, Path path, int type, String localFilePath) { super(application, path, type, MediaItem.getTargetSize(type)); LocalImageRequest(GalleryApp application, Path path, long timeModified, int type, String localFilePath) { super(application, path, timeModified, type, MediaItem.getTargetSize(type)); mLocalFilePath = localFilePath; } Loading src/com/android/gallery3d/data/LocalVideo.java +6 −4 Original line number Diff line number Diff line Loading @@ -152,15 +152,17 @@ public class LocalVideo extends LocalMediaItem { @Override public Job<Bitmap> requestImage(int type) { return new LocalVideoRequest(mApplication, getPath(), type, filePath); return new LocalVideoRequest(mApplication, getPath(), dateModifiedInSec, type, filePath); } public static class LocalVideoRequest extends ImageCacheRequest { private String mLocalFilePath; LocalVideoRequest(GalleryApp application, Path path, int type, String localFilePath) { super(application, path, type, MediaItem.getTargetSize(type)); LocalVideoRequest(GalleryApp application, Path path, long timeModified, int type, String localFilePath) { super(application, path, timeModified, type, MediaItem.getTargetSize(type)); mLocalFilePath = localFilePath; } Loading src/com/android/gallery3d/filtershow/tools/SaveImage.java +31 −51 Original line number Diff line number Diff line Loading @@ -29,8 +29,6 @@ import android.provider.MediaStore.Images; import android.provider.MediaStore.Images.ImageColumns; import android.util.Log; import com.android.gallery3d.R; import com.android.gallery3d.app.PhotoPage; import com.android.gallery3d.common.Utils; import com.android.gallery3d.exif.ExifInterface; import com.android.gallery3d.filtershow.FilterShowActivity; Loading Loading @@ -75,11 +73,6 @@ public class SaveImage { private static final String POSTFIX_JPG = ".jpg"; private static final String AUX_DIR_NAME = ".aux"; // When this is true, the source file will be saved into auxiliary directory // and hidden from MediaStore. Otherwise, the source will be kept as the // same. private static final boolean USE_AUX_DIR = true; private final Context mContext; private final Uri mSourceUri; private final Callback mCallback; Loading Loading @@ -119,8 +112,6 @@ public class SaveImage { // names starting with "local." will be deleted. // This pattern will facilitate the multiple images deletion in the auxiliary // directory. // // TODO: Move the saving into a background service. /** * @param context Loading Loading @@ -292,9 +283,8 @@ public class SaveImage { // create a local copy as usual. if (srcFile != null) { srcFile.renameTo(mDestinationFile); uri = SaveImage.insertContent(mContext, mSelectedImageUri, mDestinationFile, System.currentTimeMillis()); removeSelectedImage(); uri = SaveImage.updateUriContent(mContext, mSelectedImageUri, mDestinationFile, System.currentTimeMillis()); } } return uri; Loading Loading @@ -326,12 +316,8 @@ public class SaveImage { // 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; if (USE_AUX_DIR) { newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); } else { newSourceUri = mSourceUri; } Uri newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); // Stopgap fix for low-memory devices. while (noBitmap) { try { Loading @@ -349,39 +335,35 @@ public class SaveImage { bitmap = pipeline.renderFinalImage(bitmap, preset); updateProgress(); Object xmp = getPanoramaXMPData(mSelectedImageUri, preset); ExifInterface exif = getExifData(mSelectedImageUri); Object xmp = getPanoramaXMPData(newSourceUri, preset); ExifInterface exif = getExifData(newSourceUri); updateProgress(); // Set tags long time = System.currentTimeMillis(); exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, time, TimeZone.getDefault()); exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION, ExifInterface.Orientation.TOP_LEFT)); // Remove old thumbnail exif.removeCompressedThumbnail(); updateProgress(); // If we succeed in writing the bitmap as a jpeg, return a uri. if (putExifData(mDestinationFile, exif, bitmap)) { putPanoramaXMPData(mDestinationFile, xmp); uri = SaveImage.insertContent(mContext, mSelectedImageUri, mDestinationFile, time); } updateProgress(); // mDestinationFile will save the newSourceUri info in the XMP. XmpPresets.writeFilterXMP(mContext, newSourceUri, mDestinationFile, preset); updateProgress(); XmpPresets.writeFilterXMP(mContext, newSourceUri, mDestinationFile, preset); // Since we have a new image inserted to media store, we can // safely remove the old one which is selected by the user. // TODO: we should fix that, do an update instead of insert+remove, // as well as asking Gallery to update its cached version of the image if (USE_AUX_DIR) { removeSelectedImage(); // After this call, mSelectedImageUri will be actually // pointing at the new file mDestinationFile. uri = SaveImage.updateUriContent(mContext, mSelectedImageUri, mDestinationFile, time); } updateProgress(); noBitmap = false; UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, "SaveComplete", null); Loading @@ -398,15 +380,6 @@ public class SaveImage { return uri; } private void removeSelectedImage() { String scheme = mSelectedImageUri.getScheme(); if (scheme != null && scheme.equals(ContentResolver.SCHEME_CONTENT)) { if (mSelectedImageUri.getAuthority().equals(MediaStore.AUTHORITY)) { mContext.getContentResolver().delete(mSelectedImageUri, null, null); } } } /** * Move the source file to auxiliary directory if needed and return the Uri * pointing to this new source file. Loading Loading @@ -463,7 +436,7 @@ public class SaveImage { String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time)); File saveDirectory = getFinalSaveDirectory(context, sourceUri); File file = new File(saveDirectory, filename + ".JPG"); return insertContent(context, sourceUri, file, time); return updateUriContent(context, sourceUri, file, time); } public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, Loading Loading @@ -583,12 +556,14 @@ public class SaveImage { } /** * Insert the content (saved file) with proper source photo properties. * Update the content Uri with the new file and proper source properties. * The old file will be removed if it is local. */ public static Uri insertContent(Context context, Uri sourceUri, File file, long time) { time /= 1000; public static Uri updateUriContent(Context context, Uri sourceUri, File file, long time) { File oldSelectedFile = getLocalFileFromUri(context, sourceUri); final ContentValues values = new ContentValues(); time /= 1000; values.put(Images.Media.TITLE, file.getName()); values.put(Images.Media.DISPLAY_NAME, file.getName()); values.put(Images.Media.MIME_TYPE, "image/jpeg"); Loading Loading @@ -621,8 +596,13 @@ public class SaveImage { } }); return context.getContentResolver().insert( Images.Media.EXTERNAL_CONTENT_URI, values); context.getContentResolver().update(sourceUri, values, null, null); if (oldSelectedFile != null && oldSelectedFile.exists()) { oldSelectedFile.delete(); } return sourceUri; } } Loading
src/com/android/gallery3d/data/ImageCacheRequest.java +6 −4 Original line number Diff line number Diff line Loading @@ -32,17 +32,19 @@ abstract class ImageCacheRequest implements Job<Bitmap> { private Path mPath; private int mType; private int mTargetSize; private long mTimeModified; public ImageCacheRequest(GalleryApp application, Path path, int type, int targetSize) { Path path, long timeModified, int type, int targetSize) { mApplication = application; mPath = path; mType = type; mTargetSize = targetSize; mTimeModified = timeModified; } private String debugTag() { return mPath + "," + return mPath + "," + mTimeModified + "," + ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" : (mType == MediaItem.TYPE_MICROTHUMBNAIL) ? "MICROTHUMB" : "?"); } Loading @@ -53,7 +55,7 @@ abstract class ImageCacheRequest implements Job<Bitmap> { BytesBuffer buffer = MediaItem.getBytesBufferPool().get(); try { boolean found = cacheService.getImageData(mPath, mType, buffer); boolean found = cacheService.getImageData(mPath, mTimeModified, mType, buffer); if (jc.isCancelled()) return null; if (found) { BitmapFactory.Options options = new BitmapFactory.Options(); Loading Loading @@ -92,7 +94,7 @@ abstract class ImageCacheRequest implements Job<Bitmap> { byte[] array = BitmapUtils.compressToBytes(bitmap); if (jc.isCancelled()) return null; cacheService.putImageData(mPath, mType, array); cacheService.putImageData(mPath, mTimeModified, mType, array); return bitmap; } Loading
src/com/android/gallery3d/data/ImageCacheService.java +10 −9 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ public class ImageCacheService { } /** * Gets the cached image data for the given <code>path</code> and <code>type</code>. * Gets the cached image data for the given <code>path</code>, * <code>timeModified</code> and <code>type</code>. * * The image data will be stored in <code>buffer.data</code>, started from * <code>buffer.offset</code> for <code>buffer.length</code> bytes. If the Loading @@ -54,8 +55,8 @@ public class ImageCacheService { * * @return true if the image data is found; false if not found. */ public boolean getImageData(Path path, int type, BytesBuffer buffer) { byte[] key = makeKey(path, type); public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) { byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); try { LookupRequest request = new LookupRequest(); Loading @@ -76,8 +77,8 @@ public class ImageCacheService { return false; } public void putImageData(Path path, int type, byte[] value) { byte[] key = makeKey(path, type); public void putImageData(Path path, long timeModified, int type, byte[] value) { byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); buffer.put(key); Loading @@ -91,8 +92,8 @@ public class ImageCacheService { } } public void clearImageData(Path path, int type) { byte[] key = makeKey(path, type); public void clearImageData(Path path, long timeModified, int type) { byte[] key = makeKey(path, timeModified, type); long cacheKey = Utils.crc64Long(key); synchronized (mCache) { try { Loading @@ -103,8 +104,8 @@ public class ImageCacheService { } } private static byte[] makeKey(Path path, int type) { return GalleryUtils.getBytes(path.toString() + "+" + type); private static byte[] makeKey(Path path, long timeModified, int type) { return GalleryUtils.getBytes(path.toString() + "+" + timeModified + "+" + type); } private static boolean isSameKey(byte[] key, byte[] buffer) { Loading
src/com/android/gallery3d/data/LocalImage.java +6 −4 Original line number Diff line number Diff line Loading @@ -173,15 +173,17 @@ public class LocalImage extends LocalMediaItem { @Override public Job<Bitmap> requestImage(int type) { return new LocalImageRequest(mApplication, mPath, type, filePath); return new LocalImageRequest(mApplication, mPath, dateModifiedInSec, type, filePath); } public static class LocalImageRequest extends ImageCacheRequest { private String mLocalFilePath; LocalImageRequest(GalleryApp application, Path path, int type, String localFilePath) { super(application, path, type, MediaItem.getTargetSize(type)); LocalImageRequest(GalleryApp application, Path path, long timeModified, int type, String localFilePath) { super(application, path, timeModified, type, MediaItem.getTargetSize(type)); mLocalFilePath = localFilePath; } Loading
src/com/android/gallery3d/data/LocalVideo.java +6 −4 Original line number Diff line number Diff line Loading @@ -152,15 +152,17 @@ public class LocalVideo extends LocalMediaItem { @Override public Job<Bitmap> requestImage(int type) { return new LocalVideoRequest(mApplication, getPath(), type, filePath); return new LocalVideoRequest(mApplication, getPath(), dateModifiedInSec, type, filePath); } public static class LocalVideoRequest extends ImageCacheRequest { private String mLocalFilePath; LocalVideoRequest(GalleryApp application, Path path, int type, String localFilePath) { super(application, path, type, MediaItem.getTargetSize(type)); LocalVideoRequest(GalleryApp application, Path path, long timeModified, int type, String localFilePath) { super(application, path, timeModified, type, MediaItem.getTargetSize(type)); mLocalFilePath = localFilePath; } Loading
src/com/android/gallery3d/filtershow/tools/SaveImage.java +31 −51 Original line number Diff line number Diff line Loading @@ -29,8 +29,6 @@ import android.provider.MediaStore.Images; import android.provider.MediaStore.Images.ImageColumns; import android.util.Log; import com.android.gallery3d.R; import com.android.gallery3d.app.PhotoPage; import com.android.gallery3d.common.Utils; import com.android.gallery3d.exif.ExifInterface; import com.android.gallery3d.filtershow.FilterShowActivity; Loading Loading @@ -75,11 +73,6 @@ public class SaveImage { private static final String POSTFIX_JPG = ".jpg"; private static final String AUX_DIR_NAME = ".aux"; // When this is true, the source file will be saved into auxiliary directory // and hidden from MediaStore. Otherwise, the source will be kept as the // same. private static final boolean USE_AUX_DIR = true; private final Context mContext; private final Uri mSourceUri; private final Callback mCallback; Loading Loading @@ -119,8 +112,6 @@ public class SaveImage { // names starting with "local." will be deleted. // This pattern will facilitate the multiple images deletion in the auxiliary // directory. // // TODO: Move the saving into a background service. /** * @param context Loading Loading @@ -292,9 +283,8 @@ public class SaveImage { // create a local copy as usual. if (srcFile != null) { srcFile.renameTo(mDestinationFile); uri = SaveImage.insertContent(mContext, mSelectedImageUri, mDestinationFile, System.currentTimeMillis()); removeSelectedImage(); uri = SaveImage.updateUriContent(mContext, mSelectedImageUri, mDestinationFile, System.currentTimeMillis()); } } return uri; Loading Loading @@ -326,12 +316,8 @@ public class SaveImage { // 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; if (USE_AUX_DIR) { newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); } else { newSourceUri = mSourceUri; } Uri newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); // Stopgap fix for low-memory devices. while (noBitmap) { try { Loading @@ -349,39 +335,35 @@ public class SaveImage { bitmap = pipeline.renderFinalImage(bitmap, preset); updateProgress(); Object xmp = getPanoramaXMPData(mSelectedImageUri, preset); ExifInterface exif = getExifData(mSelectedImageUri); Object xmp = getPanoramaXMPData(newSourceUri, preset); ExifInterface exif = getExifData(newSourceUri); updateProgress(); // Set tags long time = System.currentTimeMillis(); exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, time, TimeZone.getDefault()); exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION, ExifInterface.Orientation.TOP_LEFT)); // Remove old thumbnail exif.removeCompressedThumbnail(); updateProgress(); // If we succeed in writing the bitmap as a jpeg, return a uri. if (putExifData(mDestinationFile, exif, bitmap)) { putPanoramaXMPData(mDestinationFile, xmp); uri = SaveImage.insertContent(mContext, mSelectedImageUri, mDestinationFile, time); } updateProgress(); // mDestinationFile will save the newSourceUri info in the XMP. XmpPresets.writeFilterXMP(mContext, newSourceUri, mDestinationFile, preset); updateProgress(); XmpPresets.writeFilterXMP(mContext, newSourceUri, mDestinationFile, preset); // Since we have a new image inserted to media store, we can // safely remove the old one which is selected by the user. // TODO: we should fix that, do an update instead of insert+remove, // as well as asking Gallery to update its cached version of the image if (USE_AUX_DIR) { removeSelectedImage(); // After this call, mSelectedImageUri will be actually // pointing at the new file mDestinationFile. uri = SaveImage.updateUriContent(mContext, mSelectedImageUri, mDestinationFile, time); } updateProgress(); noBitmap = false; UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, "SaveComplete", null); Loading @@ -398,15 +380,6 @@ public class SaveImage { return uri; } private void removeSelectedImage() { String scheme = mSelectedImageUri.getScheme(); if (scheme != null && scheme.equals(ContentResolver.SCHEME_CONTENT)) { if (mSelectedImageUri.getAuthority().equals(MediaStore.AUTHORITY)) { mContext.getContentResolver().delete(mSelectedImageUri, null, null); } } } /** * Move the source file to auxiliary directory if needed and return the Uri * pointing to this new source file. Loading Loading @@ -463,7 +436,7 @@ public class SaveImage { String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time)); File saveDirectory = getFinalSaveDirectory(context, sourceUri); File file = new File(saveDirectory, filename + ".JPG"); return insertContent(context, sourceUri, file, time); return updateUriContent(context, sourceUri, file, time); } public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, Loading Loading @@ -583,12 +556,14 @@ public class SaveImage { } /** * Insert the content (saved file) with proper source photo properties. * Update the content Uri with the new file and proper source properties. * The old file will be removed if it is local. */ public static Uri insertContent(Context context, Uri sourceUri, File file, long time) { time /= 1000; public static Uri updateUriContent(Context context, Uri sourceUri, File file, long time) { File oldSelectedFile = getLocalFileFromUri(context, sourceUri); final ContentValues values = new ContentValues(); time /= 1000; values.put(Images.Media.TITLE, file.getName()); values.put(Images.Media.DISPLAY_NAME, file.getName()); values.put(Images.Media.MIME_TYPE, "image/jpeg"); Loading Loading @@ -621,8 +596,13 @@ public class SaveImage { } }); return context.getContentResolver().insert( Images.Media.EXTERNAL_CONTENT_URI, values); context.getContentResolver().update(sourceUri, values, null, null); if (oldSelectedFile != null && oldSelectedFile.exists()) { oldSelectedFile.delete(); } return sourceUri; } }