summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/filtershow/tools')
-rw-r--r--src/com/android/gallery3d/filtershow/tools/IconFactory.java108
-rw-r--r--src/com/android/gallery3d/filtershow/tools/MatrixFit.java200
-rw-r--r--src/com/android/gallery3d/filtershow/tools/SaveImage.java632
-rw-r--r--src/com/android/gallery3d/filtershow/tools/XmpPresets.java133
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;
- }
-}