diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/tools')
4 files changed, 0 insertions, 1073 deletions
diff --git a/src/com/android/gallery3d/filtershow/tools/IconFactory.java b/src/com/android/gallery3d/filtershow/tools/IconFactory.java deleted file mode 100644 index 9e39f27fc..000000000 --- a/src/com/android/gallery3d/filtershow/tools/IconFactory.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; - -/** - * A factory class for producing bitmaps to use as UI icons. - */ -public class IconFactory { - - /** - * Builds an icon with the dimensions iconWidth:iconHeight. If scale is set - * the source image is stretched to fit within the given dimensions; - * otherwise, the source image is cropped to the proper aspect ratio. - * - * @param sourceImage image to create an icon from. - * @param iconWidth width of the icon bitmap. - * @param iconHeight height of the icon bitmap. - * @param scale if true, stretch sourceImage to fit the icon dimensions. - * @return an icon bitmap with the dimensions iconWidth:iconHeight. - */ - public static Bitmap createIcon(Bitmap sourceImage, int iconWidth, int iconHeight, - boolean scale) { - if (sourceImage == null) { - throw new IllegalArgumentException("Null argument to buildIcon"); - } - - int sourceWidth = sourceImage.getWidth(); - int sourceHeight = sourceImage.getHeight(); - - if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) { - throw new IllegalArgumentException("Bitmap with dimension 0 used as input"); - } - - Bitmap icon = Bitmap.createBitmap(iconWidth, iconHeight, - Bitmap.Config.ARGB_8888); - drawIcon(icon, sourceImage, scale); - return icon; - } - - /** - * Draws an icon in the destination bitmap. If scale is set the source image - * is stretched to fit within the destination dimensions; otherwise, the - * source image is cropped to the proper aspect ratio. - * - * @param dest bitmap into which to draw the icon. - * @param sourceImage image to create an icon from. - * @param scale if true, stretch sourceImage to fit the destination. - */ - public static void drawIcon(Bitmap dest, Bitmap sourceImage, boolean scale) { - if (dest == null || sourceImage == null) { - throw new IllegalArgumentException("Null argument to buildIcon"); - } - - int sourceWidth = sourceImage.getWidth(); - int sourceHeight = sourceImage.getHeight(); - int iconWidth = dest.getWidth(); - int iconHeight = dest.getHeight(); - - if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) { - throw new IllegalArgumentException("Bitmap with dimension 0 used as input"); - } - - Rect destRect = new Rect(0, 0, iconWidth, iconHeight); - Canvas canvas = new Canvas(dest); - - Rect srcRect = null; - if (scale) { - // scale image to fit in icon (stretches if aspect isn't the same) - srcRect = new Rect(0, 0, sourceWidth, sourceHeight); - } else { - // crop image to aspect ratio iconWidth:iconHeight - float wScale = sourceWidth / (float) iconWidth; - float hScale = sourceHeight / (float) iconHeight; - float s = Math.min(hScale, wScale); - - float iw = iconWidth * s; - float ih = iconHeight * s; - - float borderW = (sourceWidth - iw) / 2.0f; - float borderH = (sourceHeight - ih) / 2.0f; - RectF rec = new RectF(borderW, borderH, borderW + iw, borderH + ih); - srcRect = new Rect(); - rec.roundOut(srcRect); - } - - canvas.drawBitmap(sourceImage, srcRect, destRect, new Paint(Paint.FILTER_BITMAP_FLAG)); - } -} diff --git a/src/com/android/gallery3d/filtershow/tools/MatrixFit.java b/src/com/android/gallery3d/filtershow/tools/MatrixFit.java deleted file mode 100644 index 3b815673c..000000000 --- a/src/com/android/gallery3d/filtershow/tools/MatrixFit.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.util.Log; - -public class MatrixFit { - // Simple implementation of a matrix fit in N dimensions. - - private static final String LOGTAG = "MatrixFit"; - - private double[][] mMatrix; - private int mDimension; - private boolean mValid = false; - private static double sEPS = 1.0f/10000000000.0f; - - public MatrixFit(double[][] from, double[][] to) { - mValid = fit(from, to); - } - - public int getDimension() { - return mDimension; - } - - public boolean isValid() { - return mValid; - } - - public double[][] getMatrix() { - return mMatrix; - } - - public boolean fit(double[][] from, double[][] to) { - if ((from.length != to.length) || (from.length < 1)) { - Log.e(LOGTAG, "from and to must be of same size"); - return false; - } - - mDimension = from[0].length; - mMatrix = new double[mDimension +1][mDimension + mDimension +1]; - - if (from.length < mDimension) { - Log.e(LOGTAG, "Too few points => under-determined system"); - return false; - } - - double[][] q = new double[from.length][mDimension]; - for (int i = 0; i < from.length; i++) { - for (int j = 0; j < mDimension; j++) { - q[i][j] = from[i][j]; - } - } - - double[][] p = new double[to.length][mDimension]; - for (int i = 0; i < to.length; i++) { - for (int j = 0; j < mDimension; j++) { - p[i][j] = to[i][j]; - } - } - - // Make an empty (dim) x (dim + 1) matrix and fill it - double[][] c = new double[mDimension+1][mDimension]; - for (int j = 0; j < mDimension; j++) { - for (int k = 0; k < mDimension + 1; k++) { - for (int i = 0; i < q.length; i++) { - double qt = 1; - if (k < mDimension) { - qt = q[i][k]; - } - c[k][j] += qt * p[i][j]; - } - } - } - - // Make an empty (dim+1) x (dim+1) matrix and fill it - double[][] Q = new double[mDimension+1][mDimension+1]; - for (int qi = 0; qi < q.length; qi++) { - double[] qt = new double[mDimension + 1]; - for (int i = 0; i < mDimension; i++) { - qt[i] = q[qi][i]; - } - qt[mDimension] = 1; - for (int i = 0; i < mDimension + 1; i++) { - for (int j = 0; j < mDimension + 1; j++) { - Q[i][j] += qt[i] * qt[j]; - } - } - } - - // Use a gaussian elimination to solve the linear system - for (int i = 0; i < mDimension + 1; i++) { - for (int j = 0; j < mDimension + 1; j++) { - mMatrix[i][j] = Q[i][j]; - } - for (int j = 0; j < mDimension; j++) { - mMatrix[i][mDimension + 1 + j] = c[i][j]; - } - } - if (!gaussianElimination(mMatrix)) { - return false; - } - return true; - } - - public double[] apply(double[] point) { - if (mDimension != point.length) { - return null; - } - double[] res = new double[mDimension]; - for (int j = 0; j < mDimension; j++) { - for (int i = 0; i < mDimension; i++) { - res[j] += point[i] * mMatrix[i][j+ mDimension +1]; - } - res[j] += mMatrix[mDimension][j+ mDimension +1]; - } - return res; - } - - public void printEquation() { - for (int j = 0; j < mDimension; j++) { - String str = "x" + j + "' = "; - for (int i = 0; i < mDimension; i++) { - str += "x" + i + " * " + mMatrix[i][j+mDimension+1] + " + "; - } - str += mMatrix[mDimension][j+mDimension+1]; - Log.v(LOGTAG, str); - } - } - - private void printMatrix(String name, double[][] matrix) { - Log.v(LOGTAG, "name: " + name); - for (int i = 0; i < matrix.length; i++) { - String str = ""; - for (int j = 0; j < matrix[0].length; j++) { - str += "" + matrix[i][j] + " "; - } - Log.v(LOGTAG, str); - } - } - - /* - * Transforms the given matrix into a row echelon matrix - */ - private boolean gaussianElimination(double[][] m) { - int h = m.length; - int w = m[0].length; - - for (int y = 0; y < h; y++) { - int maxrow = y; - for (int y2 = y + 1; y2 < h; y2++) { // Find max pivot - if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y])) { - maxrow = y2; - } - } - // swap - for (int i = 0; i < mDimension; i++) { - double t = m[y][i]; - m[y][i] = m[maxrow][i]; - m[maxrow][i] = t; - } - - if (Math.abs(m[y][y]) <= sEPS) { // Singular Matrix - return false; - } - for (int y2 = y + 1; y2 < h; y2++) { // Eliminate column y - double c = m[y2][y] / m[y][y]; - for (int x = y; x < w; x++) { - m[y2][x] -= m[y][x] * c; - } - } - } - for (int y = h -1; y > -1; y--) { // Back substitution - double c = m[y][y]; - for (int y2 = 0; y2 < y; y2++) { - for (int x = w - 1; x > y - 1; x--) { - m[y2][x] -= m[y][x] * m[y2][y] / c; - } - } - m[y][y] /= c; - for (int x = h; x < w; x++) { // Normalize row y - m[y][x] /= c; - } - } - return true; - } -} diff --git a/src/com/android/gallery3d/filtershow/tools/SaveImage.java b/src/com/android/gallery3d/filtershow/tools/SaveImage.java deleted file mode 100644 index 83cbd0136..000000000 --- a/src/com/android/gallery3d/filtershow/tools/SaveImage.java +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.util.Log; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.filtershow.FilterShowActivity; -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 com.android.gallery3d.util.XmpUtilHelper; - -import java.io.File; -import java.io.FileNotFoundException; -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; - -/** - * Handles saving edited photo - */ -public class SaveImage { - private static final String LOGTAG = "SaveImage"; - - /** - * Callback for updates - */ - public interface Callback { - void onProgress(int max, int current); - } - - public interface ContentResolverQueryCallback { - void onCursorResult(Cursor cursor); - } - - private static final String TIME_STAMP_NAME = "_yyyyMMdd_HHmmss"; - private static final String PREFIX_PANO = "PANO"; - private static final String PREFIX_IMG = "IMG"; - private static final String POSTFIX_JPG = ".jpg"; - private static final String AUX_DIR_NAME = ".aux"; - - private final Context mContext; - private final Uri mSourceUri; - private final Callback mCallback; - private final File mDestinationFile; - private final Uri mSelectedImageUri; - - private int mCurrentProcessingStep = 1; - - public static final int MAX_PROCESSING_STEPS = 6; - public static final String DEFAULT_SAVE_DIRECTORY = "EditedOnlinePhotos"; - - // In order to support the new edit-save behavior such that user won't see - // the edited image together with the original image, we are adding a new - // auxiliary directory for the edited image. Basically, the original image - // will be hidden in that directory after edit and user will see the edited - // image only. - // Note that deletion on the edited image will also cause the deletion of - // the original image under auxiliary directory. - // - // There are several situations we need to consider: - // 1. User edit local image local01.jpg. A local02.jpg will be created in the - // same directory, and original image will be moved to auxiliary directory as - // ./.aux/local02.jpg. - // If user edit the local02.jpg, local03.jpg will be created in the local - // directory and ./.aux/local02.jpg will be renamed to ./.aux/local03.jpg - // - // 2. User edit remote image remote01.jpg from picassa or other server. - // remoteSavedLocal01.jpg will be saved under proper local directory. - // In remoteSavedLocal01.jpg, there will be a reference pointing to the - // remote01.jpg. There will be no local copy of remote01.jpg. - // If user edit remoteSavedLocal01.jpg, then a new remoteSavedLocal02.jpg - // will be generated and still pointing to the remote01.jpg - // - // 3. User delete any local image local.jpg. - // Since the filenames are kept consistent in auxiliary directory, every - // time a local.jpg get deleted, the files in auxiliary directory whose - // names starting with "local." will be deleted. - // This pattern will facilitate the multiple images deletion in the auxiliary - // directory. - - /** - * @param context - * @param sourceUri The Uri for the original image, which can be the hidden - * image under the auxiliary directory or the same as selectedImageUri. - * @param selectedImageUri The Uri for the image selected by the user. - * In most cases, it is a content Uri for local image or remote image. - * @param destination Destinaton File, if this is null, a new file will be - * created under the same directory as selectedImageUri. - * @param callback Let the caller know the saving has completed. - * @return the newSourceUri - */ - public SaveImage(Context context, Uri sourceUri, Uri selectedImageUri, - File destination, Callback callback) { - mContext = context; - mSourceUri = sourceUri; - mCallback = callback; - if (destination == null) { - mDestinationFile = getNewFile(context, selectedImageUri); - } else { - mDestinationFile = destination; - } - - mSelectedImageUri = selectedImageUri; - } - - public static File getFinalSaveDirectory(Context context, Uri sourceUri) { - File saveDirectory = SaveImage.getSaveDirectory(context, sourceUri); - if ((saveDirectory == null) || !saveDirectory.canWrite()) { - saveDirectory = new File(Environment.getExternalStorageDirectory(), - SaveImage.DEFAULT_SAVE_DIRECTORY); - } - // Create the directory if it doesn't exist - if (!saveDirectory.exists()) - saveDirectory.mkdirs(); - return saveDirectory; - } - - public static File getNewFile(Context context, Uri sourceUri) { - File saveDirectory = getFinalSaveDirectory(context, sourceUri); - String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date( - System.currentTimeMillis())); - if (hasPanoPrefix(context, sourceUri)) { - return new File(saveDirectory, PREFIX_PANO + filename + POSTFIX_JPG); - } - return new File(saveDirectory, PREFIX_IMG + filename + POSTFIX_JPG); - } - - /** - * Remove the files in the auxiliary directory whose names are the same as - * the source image. - * @param contentResolver The application's contentResolver - * @param srcContentUri The content Uri for the source image. - */ - public static void deleteAuxFiles(ContentResolver contentResolver, - Uri srcContentUri) { - final String[] fullPath = new String[1]; - String[] queryProjection = new String[] { ImageColumns.DATA }; - querySourceFromContentResolver(contentResolver, - srcContentUri, queryProjection, - new ContentResolverQueryCallback() { - @Override - public void onCursorResult(Cursor cursor) { - fullPath[0] = cursor.getString(0); - } - } - ); - if (fullPath[0] != null) { - // Construct the auxiliary directory given the source file's path. - // Then select and delete all the files starting with the same name - // under the auxiliary directory. - File currentFile = new File(fullPath[0]); - - String filename = currentFile.getName(); - int firstDotPos = filename.indexOf("."); - final String filenameNoExt = (firstDotPos == -1) ? filename : - filename.substring(0, firstDotPos); - File auxDir = getLocalAuxDirectory(currentFile); - if (auxDir.exists()) { - FilenameFilter filter = new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - if (name.startsWith(filenameNoExt + ".")) { - return true; - } else { - return false; - } - } - }; - - // Delete all auxiliary files whose name is matching the - // current local image. - File[] auxFiles = auxDir.listFiles(filter); - for (File file : auxFiles) { - file.delete(); - } - } - } - } - - public Object getPanoramaXMPData(Uri source, ImagePreset preset) { - Object xmp = null; - if (preset.isPanoramaSafe()) { - InputStream is = null; - try { - is = mContext.getContentResolver().openInputStream(source); - xmp = XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "Failed to get XMP data from image: ", e); - } finally { - Utils.closeSilently(is); - } - } - return xmp; - } - - public boolean putPanoramaXMPData(File file, Object xmp) { - if (xmp != null) { - return XmpUtilHelper.writeXMPMeta(file.getAbsolutePath(), xmp); - } - return false; - } - - public ExifInterface getExifData(Uri source) { - ExifInterface exif = new ExifInterface(); - String mimeType = mContext.getContentResolver().getType(mSelectedImageUri); - if (mimeType == null) { - mimeType = ImageLoader.getMimeType(mSelectedImageUri); - } - if (mimeType.equals(ImageLoader.JPEG_MIME_TYPE)) { - InputStream inStream = null; - try { - inStream = mContext.getContentResolver().openInputStream(source); - exif.readExif(inStream); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "Cannot find file: " + source, e); - } catch (IOException e) { - Log.w(LOGTAG, "Cannot read exif for: " + source, e); - } finally { - Utils.closeSilently(inStream); - } - } - return exif; - } - - public boolean putExifData(File file, ExifInterface exif, Bitmap image, - int jpegCompressQuality) { - boolean ret = false; - OutputStream s = null; - try { - 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, boolean doAuxBackup) { - Uri uri = null; - if (!preset.hasModifications()) { - // This can happen only when preset has no modification but save - // button is enabled, it means the file is loaded with filters in - // the XMP, then all the filters are removed or restore to default. - // In this case, when mSourceUri exists, rename it to the - // destination file. - File srcFile = getLocalFileFromUri(mContext, mSourceUri); - // If the source is not a local file, then skip this renaming and - // create a local copy as usual. - if (srcFile != null) { - srcFile.renameTo(mDestinationFile); - uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri, - mDestinationFile, System.currentTimeMillis(), doAuxBackup); - } - } - return uri; - } - - private void resetProgress() { - mCurrentProcessingStep = 0; - } - - private void updateProgress() { - if (mCallback != null) { - mCallback.onProgress(MAX_PROCESSING_STEPS, ++mCurrentProcessingStep); - } - } - - public Uri processAndSaveImage(ImagePreset preset, boolean doAuxBackup, int quality) { - - Uri uri = resetToOriginalImageIfNeeded(preset, doAuxBackup); - if (uri != null) { - return null; - } - - resetProgress(); - - boolean noBitmap = true; - int num_tries = 0; - int sampleSize = 1; - - // 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 = mSourceUri; - if (doAuxBackup) { - newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); - } - - // Stopgap fix for low-memory devices. - while (noBitmap) { - try { - updateProgress(); - // Try to do bitmap operations, downsample if low-memory - Bitmap bitmap = ImageLoader.loadOrientedBitmapWithBackouts(mContext, newSourceUri, - sampleSize); - if (bitmap == null) { - return null; - } - updateProgress(); - CachingPipeline pipeline = new CachingPipeline(FiltersManager.getManager(), - "Saving"); - - bitmap = pipeline.renderFinalImage(bitmap, preset); - updateProgress(); - - 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, quality)) { - putPanoramaXMPData(mDestinationFile, xmp); - // mDestinationFile will save the newSourceUri info in the XMP. - XmpPresets.writeFilterXMP(mContext, newSourceUri, - mDestinationFile, preset); - - // After this call, mSelectedImageUri will be actually - // pointing at the new file mDestinationFile. - uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri, - mDestinationFile, time, doAuxBackup); - } - updateProgress(); - - noBitmap = false; - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - "SaveComplete", null); - } catch (OutOfMemoryError e) { - // Try 5 times before failing for good. - if (++num_tries >= 5) { - throw e; - } - System.gc(); - sampleSize *= 2; - resetProgress(); - } - } - return uri; - } - - /** - * Move the source file to auxiliary directory if needed and return the Uri - * pointing to this new source file. - * @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. - * @return the newSourceUri pointing to the new source image. - */ - private Uri moveSrcToAuxIfNeeded(Uri srcUri, File dstFile) { - File srcFile = getLocalFileFromUri(mContext, srcUri); - if (srcFile == null) { - Log.d(LOGTAG, "Source file is not a local file, no update."); - return srcUri; - } - - // Get the destination directory and create the auxilliary directory - // if necessary. - File auxDiretory = getLocalAuxDirectory(dstFile); - if (!auxDiretory.exists()) { - auxDiretory.mkdirs(); - } - - // Make sure there is a .nomedia file in the auxiliary directory, such - // that MediaScanner will not report those files under this directory. - File noMedia = new File(auxDiretory, ".nomedia"); - if (!noMedia.exists()) { - try { - noMedia.createNewFile(); - } catch (IOException e) { - Log.e(LOGTAG, "Can't create the nomedia"); - return srcUri; - } - } - // 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()); - - if (!newSrcFile.exists()) { - srcFile.renameTo(newSrcFile); - } - - return Uri.fromFile(newSrcFile); - - } - - private static File getLocalAuxDirectory(File dstFile) { - File dstDirectory = dstFile.getParentFile(); - File auxDiretory = new File(dstDirectory + "/" + AUX_DIR_NAME); - return auxDiretory; - } - - public static Uri makeAndInsertUri(Context context, Uri sourceUri) { - long time = System.currentTimeMillis(); - 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, false); - } - - public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, - File destination) { - Uri selectedImageUri = filterShowActivity.getSelectedImageUri(); - Uri sourceImageUri = MasterImage.getImage().getUri(); - - Intent processIntent = ProcessingService.getSaveIntent(filterShowActivity, preset, - destination, selectedImageUri, sourceImageUri, false, 90); - - filterShowActivity.startService(processIntent); - - if (!filterShowActivity.isSimpleEditAction()) { - // terminate for now - filterShowActivity.completeSaveImage(selectedImageUri); - } - } - - public static void querySource(Context context, Uri sourceUri, String[] projection, - ContentResolverQueryCallback callback) { - ContentResolver contentResolver = context.getContentResolver(); - querySourceFromContentResolver(contentResolver, sourceUri, projection, callback); - } - - private static void querySourceFromContentResolver( - ContentResolver contentResolver, Uri sourceUri, String[] projection, - ContentResolverQueryCallback callback) { - Cursor cursor = null; - try { - cursor = contentResolver.query(sourceUri, projection, null, null, - null); - if ((cursor != null) && cursor.moveToNext()) { - callback.onCursorResult(cursor); - } - } catch (Exception e) { - // Ignore error for lacking the data column from the source. - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - private static File getSaveDirectory(Context context, Uri sourceUri) { - File file = getLocalFileFromUri(context, sourceUri); - if (file != null) { - return file.getParentFile(); - } else { - return null; - } - } - - /** - * Construct a File object based on the srcUri. - * @return The file object. Return null if srcUri is invalid or not a local - * file. - */ - private static File getLocalFileFromUri(Context context, Uri srcUri) { - if (srcUri == null) { - Log.e(LOGTAG, "srcUri is null."); - return null; - } - - String scheme = srcUri.getScheme(); - if (scheme == null) { - Log.e(LOGTAG, "scheme is null."); - return null; - } - - final File[] file = new File[1]; - // sourceUri can be a file path or a content Uri, it need to be handled - // differently. - if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { - if (srcUri.getAuthority().equals(MediaStore.AUTHORITY)) { - querySource(context, srcUri, new String[] { - ImageColumns.DATA - }, - new ContentResolverQueryCallback() { - - @Override - public void onCursorResult(Cursor cursor) { - file[0] = new File(cursor.getString(0)); - } - }); - } - } else if (scheme.equals(ContentResolver.SCHEME_FILE)) { - file[0] = new File(srcUri.getPath()); - } - return file[0]; - } - - /** - * Gets the actual filename for a Uri from Gallery's ContentProvider. - */ - private static String getTrueFilename(Context context, Uri src) { - if (context == null || src == null) { - return null; - } - final String[] trueName = new String[1]; - querySource(context, src, new String[] { - ImageColumns.DATA - }, new ContentResolverQueryCallback() { - @Override - public void onCursorResult(Cursor cursor) { - trueName[0] = new File(cursor.getString(0)).getName(); - } - }); - return trueName[0]; - } - - /** - * Checks whether the true filename has the panorama image prefix. - */ - private static boolean hasPanoPrefix(Context context, Uri src) { - String name = getTrueFilename(context, src); - return name != null && name.startsWith(PREFIX_PANO); - } - - /** - * If the <code>sourceUri</code> is a local content Uri, update the - * <code>sourceUri</code> to point to the <code>file</code>. - * At the same time, the old file <code>sourceUri</code> used to point to - * will be removed if it is local. - * If the <code>sourceUri</code> is not a local content Uri, then the - * <code>file</code> will be inserted as a new content Uri. - * @return the final Uri referring to the <code>file</code>. - */ - public static Uri linkNewFileToUri(Context context, Uri sourceUri, - File file, long time, boolean deleteOriginal) { - 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"); - values.put(Images.Media.DATE_TAKEN, time); - values.put(Images.Media.DATE_MODIFIED, time); - values.put(Images.Media.DATE_ADDED, time); - values.put(Images.Media.ORIENTATION, 0); - values.put(Images.Media.DATA, file.getAbsolutePath()); - values.put(Images.Media.SIZE, file.length()); - - final String[] projection = new String[] { - ImageColumns.DATE_TAKEN, - ImageColumns.LATITUDE, ImageColumns.LONGITUDE, - }; - SaveImage.querySource(context, sourceUri, projection, - new SaveImage.ContentResolverQueryCallback() { - - @Override - public void onCursorResult(Cursor cursor) { - values.put(Images.Media.DATE_TAKEN, cursor.getLong(0)); - - double latitude = cursor.getDouble(1); - double longitude = cursor.getDouble(2); - // TODO: Change || to && after the default location - // issue is fixed. - if ((latitude != 0f) || (longitude != 0f)) { - values.put(Images.Media.LATITUDE, latitude); - values.put(Images.Media.LONGITUDE, longitude); - } - } - }); - - Uri result = sourceUri; - if (oldSelectedFile == null || !deleteOriginal) { - result = context.getContentResolver().insert( - Images.Media.EXTERNAL_CONTENT_URI, values); - } else { - context.getContentResolver().update(sourceUri, values, null, null); - if (oldSelectedFile.exists()) { - oldSelectedFile.delete(); - } - } - - return result; - } - -} diff --git a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java deleted file mode 100644 index 3995eeb85..000000000 --- a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.content.Context; -import android.net.Uri; -import android.util.Log; - -import com.adobe.xmp.XMPException; -import com.adobe.xmp.XMPMeta; -import com.adobe.xmp.XMPMetaFactory; -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.util.XmpUtilHelper; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; - -public class XmpPresets { - public static final String - XMP_GOOGLE_FILTER_NAMESPACE = "http://ns.google.com/photos/1.0/filter/"; - public static final String XMP_GOOGLE_FILTER_PREFIX = "AFltr"; - public static final String XMP_SRC_FILE_URI = "SourceFileUri"; - public static final String XMP_FILTERSTACK = "filterstack"; - private static final String LOGTAG = "XmpPresets"; - - public static class XMresults { - public String presetString; - public ImagePreset preset; - public Uri originalimage; - } - - static { - try { - XMPMetaFactory.getSchemaRegistry().registerNamespace( - XMP_GOOGLE_FILTER_NAMESPACE, XMP_GOOGLE_FILTER_PREFIX); - } catch (XMPException e) { - Log.e(LOGTAG, "Register XMP name space failed", e); - } - } - - public static void writeFilterXMP( - Context context, Uri srcUri, File dstFile, ImagePreset preset) { - InputStream is = null; - XMPMeta xmpMeta = null; - try { - is = context.getContentResolver().openInputStream(srcUri); - xmpMeta = XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - - } finally { - Utils.closeSilently(is); - } - - if (xmpMeta == null) { - xmpMeta = XMPMetaFactory.create(); - } - try { - xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_SRC_FILE_URI, srcUri.toString()); - xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_FILTERSTACK, preset.getJsonString(context.getString(R.string.saved))); - } catch (XMPException e) { - Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath()); - return; - } - - if (!XmpUtilHelper.writeXMPMeta(dstFile.getAbsolutePath(), xmpMeta)) { - Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath()); - } - } - - public static XMresults extractXMPData( - Context context, MasterImage mMasterImage, Uri uriToEdit) { - XMresults ret = new XMresults(); - - InputStream is = null; - XMPMeta xmpMeta = null; - try { - is = context.getContentResolver().openInputStream(uriToEdit); - xmpMeta = XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - } finally { - Utils.closeSilently(is); - } - - if (xmpMeta == null) { - return null; - } - - try { - String strSrcUri = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_SRC_FILE_URI); - - if (strSrcUri != null) { - String filterString = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_FILTERSTACK); - - Uri srcUri = Uri.parse(strSrcUri); - ret.originalimage = srcUri; - - ret.preset = new ImagePreset(mMasterImage.getPreset()); - ret.presetString = filterString; - boolean ok = ret.preset.readJsonFromString(filterString); - if (!ok) { - return null; - } - return ret; - } - } catch (XMPException e) { - e.printStackTrace(); - } - - return null; - } -} |