Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fceb9ff0 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Passing the full image and crop hint when setting the wallpaper

Bug: 25454157
Change-Id: Ia0ae7dd4963b72cd7902622847deedfcb5a0eca2
parent 0a197dbb
Loading
Loading
Loading
Loading
+41 −26
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ import java.io.InputStream;
public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {

    public interface OnBitmapCroppedHandler {
        public void onBitmapCropped(byte[] imageBytes);
        public void onBitmapCropped(byte[] imageBytes, Rect cropHint);
    }

    public interface OnEndCropHandler {
@@ -171,29 +171,42 @@ public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {
    public boolean cropBitmap(int whichWallpaper) {
        boolean failure = false;


        WallpaperManager wallpaperManager = null;
        if (mSetWallpaper) {
            wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
        }


        if (mSetWallpaper && mNoCrop) {
            try {
                InputStream is = regenerateInputStream();
                if (is != null) {
                    if (!Utilities.isNycOrAbove()) {
                        wallpaperManager.setStream(is);
                    } else {
                        NycWallpaperUtils.setStream(mContext, is, null, true, whichWallpaper);
                    }
                setWallpaper(is, null, whichWallpaper);
                Utils.closeSilently(is);
                }
            } catch (IOException e) {
                Log.w(LOGTAG, "cannot write stream to wallpaper", e);
                failure = true;
            }
            return !failure;
        } else if (mSetWallpaper && Utilities.isNycOrAbove()
                && mRotation == 0 && mOutWidth > 0 && mOutHeight > 0) {
            Rect hint = new Rect();
            mCropBounds.roundOut(hint);

            InputStream is = null;
            try {
                is = regenerateInputStream();
                if (is == null) {
                    Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
                    failure = true;
                    return false;
                }
                WallpaperManager.getInstance(mContext).suggestDesiredDimensions(mOutWidth, mOutHeight);
                setWallpaper(is, hint, whichWallpaper);

                if (mOnBitmapCroppedHandler != null) {
                    mOnBitmapCroppedHandler.onBitmapCropped(null, hint);
                }

                failure = false;
            } catch (IOException e) {
                Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
            } finally {
                Utils.closeSilently(is);
            }
        } else {
            // Find crop bounds (scaled to original image size)
            Rect roundedTrueCrop = new Rect();
@@ -222,7 +235,6 @@ public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {
                mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2);
                inverseRotateMatrix.mapRect(mCropBounds);
                mCropBounds.offset(bounds.x/2, bounds.y/2);

            }

            mCropBounds.roundOut(roundedTrueCrop);
@@ -369,18 +381,13 @@ public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {
            ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
            if (crop.compress(CompressFormat.JPEG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
                // If we need to set to the wallpaper, set it
                if (mSetWallpaper && wallpaperManager != null) {
                if (mSetWallpaper) {
                    try {
                        byte[] outByteArray = tmpOut.toByteArray();
                        if (!Utilities.isNycOrAbove()) {
                            wallpaperManager.setStream(new ByteArrayInputStream(outByteArray));
                        } else {
                            NycWallpaperUtils.setStream(mContext,
                                    new ByteArrayInputStream(outByteArray), null, true,
                                    whichWallpaper);
                        }
                        setWallpaper(new ByteArrayInputStream(outByteArray), null, whichWallpaper);
                        if (mOnBitmapCroppedHandler != null) {
                            mOnBitmapCroppedHandler.onBitmapCropped(outByteArray);
                            mOnBitmapCroppedHandler.onBitmapCropped(outByteArray,
                                    new Rect(0, 0, crop.getWidth(), crop.getHeight()));
                        }
                    } catch (IOException e) {
                        Log.w(LOGTAG, "cannot write stream to wallpaper", e);
@@ -409,4 +416,12 @@ public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {
            mOnEndCropHandler.run(cropSucceeded);
        }
    }

    private void setWallpaper(InputStream in, Rect crop, int whichWallpaper) throws IOException {
        if (!Utilities.isNycOrAbove()) {
            WallpaperManager.getInstance(mContext.getApplicationContext()).setStream(in);
        } else {
            NycWallpaperUtils.setStream(mContext, in, crop, true, whichWallpaper);
        }
    }
}
 No newline at end of file
+13 −12
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.launcher3;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -148,10 +149,17 @@ public class CropView extends TiledImageView implements OnScaleGestureListener
        updateMinScale(w, h, mRenderer.source, false);
    }

    public void setScale(float scale) {
    public void setScaleAndCenter(float scale, float x, float y) {
        synchronized (mLock) {
            mRenderer.scale = scale;
            mCenterX = x;
            mCenterY = y;
            updateCenter();
        }
    }

    public float getScale() {
        return mRenderer.scale;
    }

    private void updateMinScale(int w, int h, TileSource source, boolean resetScale) {
@@ -189,17 +197,6 @@ public class CropView extends TiledImageView implements OnScaleGestureListener
    public void onScaleEnd(ScaleGestureDetector detector) {
    }

    /**
     * Offsets wallpaper preview according to the state it will be displayed in upon returning home.
     * @param offset Ranges from 0 to 1, where 0 is the leftmost parallax and 1 is the rightmost.
     */
    public void setParallaxOffset(float offset, RectF crop) {
        offset = Math.max(0, Math.min(offset, 1)); // Make sure the offset is in the correct range.
        float screenWidth = getWidth() / mRenderer.scale;
        mCenterX = screenWidth / 2 + offset * (crop.width() - screenWidth) + crop.left;
        updateCenter();
    }

    public void moveToLeft() {
        if (getWidth() == 0 || getHeight() == 0) {
            final ViewTreeObserver observer = getViewTreeObserver();
@@ -222,6 +219,10 @@ public class CropView extends TiledImageView implements OnScaleGestureListener
        mRenderer.centerY = Math.round(mCenterY);
    }

    public PointF getCenter() {
        return new PointF(mCenterX, mCenterY);
    }

    public void setTouchEnabled(boolean enabled) {
        mTouchEnabled = enabled;
    }
+99 −22
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -33,9 +35,14 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;

import com.android.launcher3.WallpaperCropActivity.CropViewScaleAndOffsetProvider;
import com.android.photos.views.TiledImageRenderer.TileSource;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;


@@ -48,15 +55,42 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {

    public static class SavedWallpaperTile extends WallpaperPickerActivity.FileWallpaperInfo {
        private int mDbId;
        public SavedWallpaperTile(int dbId, File target, Drawable thumb) {

        // three floats representing scale, centerX and centerY of the crop view in order.
        private Float[] mExtras;
        public SavedWallpaperTile(int dbId, File target, Drawable thumb, Float[] extras) {
            super(target, thumb);
            mDbId = dbId;
            mExtras = extras != null && extras.length == 3 ? extras : null;
        }

        @Override
        public void onDelete(WallpaperPickerActivity a) {
            a.getSavedImages().deleteImage(mDbId);
        }

        @Override
        protected CropViewScaleAndOffsetProvider getCropViewScaleAndOffsetProvider() {
            if (mExtras != null) {
                return new CropViewScaleAndOffsetProvider() {
                    @Override
                    public void updateCropView(WallpaperCropActivity a, TileSource src) {
                        a.mCropView.setScaleAndCenter(mExtras[0], mExtras[1], mExtras[2]);
                    }
                };
            }
            return null;
        }

        @Override
        public void onSave(final WallpaperPickerActivity a) {
            if (mExtras == null) {
                super.onSave(a);
            } else {
                boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
                a.cropImageAndSetWallpaper(Uri.fromFile(mFile), null, true, shouldFadeOutOnFinish);
            }
        }
    }

    public SavedWallpaperImages(Context context) {
@@ -74,7 +108,8 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
        Cursor result = db.query(ImageDb.TABLE_NAME,
                new String[] { ImageDb.COLUMN_ID,
                    ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
                    ImageDb.COLUMN_IMAGE_FILENAME}, // cols to return
                    ImageDb.COLUMN_IMAGE_FILENAME,
                    ImageDb.COLUMN_EXTRAS}, // cols to return
                null, // select query
                null, // args to select query
                null,
@@ -88,9 +123,25 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {

            Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath());
            if (thumb != null) {

                Float[] extras = null;
                String extraStr = result.getString(3);
                if (extraStr != null) {
                    String[] parts = extraStr.split(",");
                    extras = new Float[parts.length];
                    for (int i = 0; i < parts.length; i++) {
                        try {
                            extras[i] = Float.parseFloat(parts[i]);
                        } catch (Exception e) {
                            extras = null;
                            break;
                        }
                    }
                }

                mImages.add(new SavedWallpaperTile(result.getInt(0),
                        new File(mContext.getFilesDir(), result.getString(2)),
                        new BitmapDrawable(thumb)));
                        new BitmapDrawable(thumb), extras));
            }
        }
        result.close();
@@ -155,11 +206,31 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {

    public void writeImage(Bitmap thumbnail, byte[] imageBytes) {
        try {
            writeImage(thumbnail, new ByteArrayInputStream(imageBytes), null);
        } catch (IOException e) {
            Log.e(TAG, "Failed writing images to storage " + e);
        }
    }

    public void writeImage(Bitmap thumbnail, Uri uri, Float[] extras) {
        try {
            writeImage(thumbnail, mContext.getContentResolver().openInputStream(uri), extras);
        } catch (IOException e) {
            Log.e(TAG, "Failed writing images to storage " + e);
        }
    }

    private void writeImage(Bitmap thumbnail, InputStream in, Float[] extras) throws IOException {
        File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir());
        FileOutputStream imageFileStream =
                mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE);
            imageFileStream.write(imageBytes);
        byte[] buf = new byte[4096];    // 4k
        int len;
        while ((len = in.read(buf)) > 0) {
            imageFileStream.write(buf, 0, len);
        }
        imageFileStream.close();
        in.close();

        File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir());
        FileOutputStream thumbFileStream =
@@ -171,18 +242,19 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
        ContentValues values = new ContentValues();
        values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName());
        values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName());
            db.insert(ImageDb.TABLE_NAME, null, values);
        } catch (IOException e) {
            Log.e(TAG, "Failed writing images to storage " + e);
        if (extras != null) {
            values.put(ImageDb.COLUMN_EXTRAS, TextUtils.join(",", extras));
        }
        db.insert(ImageDb.TABLE_NAME, null, values);
    }

    static class ImageDb extends SQLiteOpenHelper {
        final static int DB_VERSION = 1;
        final static int DB_VERSION = 2;
        final static String TABLE_NAME = "saved_wallpaper_images";
        final static String COLUMN_ID = "id";
        final static String COLUMN_IMAGE_THUMBNAIL_FILENAME = "image_thumbnail";
        final static String COLUMN_IMAGE_FILENAME = "image";
        final static String COLUMN_EXTRAS = "extras";

        Context mContext;

@@ -209,15 +281,20 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
                    COLUMN_ID + " INTEGER NOT NULL, " +
                    COLUMN_IMAGE_THUMBNAIL_FILENAME + " TEXT NOT NULL, " +
                    COLUMN_IMAGE_FILENAME + " TEXT NOT NULL, " +
                    COLUMN_EXTRAS + " TEXT, " +
                    "PRIMARY KEY (" + COLUMN_ID + " ASC) " +
                    ");");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            if (oldVersion != newVersion) {
            if (oldVersion == 1) {
                // Add extras column
                db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COLUMN_EXTRAS + " TEXT;");
            } else if (oldVersion != newVersion) {
                // Delete all the records; they'll be repopulated as this is a cache
                db.execSQL("DELETE FROM " + TABLE_NAME);
                onCreate(db);
            }
        }
    }
+29 −10
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Build;
@@ -269,13 +270,7 @@ public class WallpaperCropActivity extends BaseActivity implements Handler.Callb
                mCropView.moveToLeft();
            }
            if (req.scaleAndOffsetProvider != null) {
                TileSource src = req.result;
                Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
                        getResources(), getWindowManager());
                RectF crop = Utils.getMaxCropRect(src.getImageWidth(), src.getImageHeight(),
                        wallpaperSize.x, wallpaperSize.y, false /* leftAligned */);
                mCropView.setScale(req.scaleAndOffsetProvider.getScale(wallpaperSize, crop));
                mCropView.setParallaxOffset(req.scaleAndOffsetProvider.getParallaxOffset(), crop);
                req.scaleAndOffsetProvider.updateCropView(this, req.result);
            }

            // Free last image
@@ -502,8 +497,32 @@ public class WallpaperCropActivity extends BaseActivity implements Handler.Callb
        TileSource result;
    }

    interface CropViewScaleAndOffsetProvider {
        float getScale(Point wallpaperSize, RectF crop);
        float getParallaxOffset();
    public static class CropViewScaleAndOffsetProvider {
        public float getScale(Point wallpaperSize, RectF crop) {
            return 1f;
        }

        public float getParallaxOffset() {
            return 0.5f;
        }

        public void updateCropView(WallpaperCropActivity a, TileSource src) {
            Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
                    a.getResources(), a.getWindowManager());
            RectF crop = Utils.getMaxCropRect(src.getImageWidth(), src.getImageHeight(),
                    wallpaperSize.x, wallpaperSize.y, false /* leftAligned */);

            float scale = getScale(wallpaperSize, crop);
            PointF center = a.mCropView.getCenter();

            // Offsets wallpaper preview according to the state it will be displayed in upon
            // returning home. Offset ranges from 0 to 1, where 0 is the leftmost parallax and
            // 1 is the rightmost.
            // Make sure the offset is in the correct range.
            float offset = Math.max(0, Math.min(getParallaxOffset(), 1));
            float screenWidth = a.mCropView.getWidth() / scale;
            center.x = screenWidth / 2 + offset * (crop.width() - screenWidth) + crop.left;
            a.mCropView.setScaleAndCenter(scale, center.x, center.y);
        }
    }
}
+51 −19
Original line number Diff line number Diff line
@@ -31,10 +31,13 @@ import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -83,6 +86,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

public class WallpaperPickerActivity extends WallpaperCropActivity {
@@ -174,12 +178,45 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
        public void onSave(final WallpaperPickerActivity a) {
            boolean finishActivityWhenDone = true;
            BitmapCropTask.OnBitmapCroppedHandler h = new BitmapCropTask.OnBitmapCroppedHandler() {
                public void onBitmapCropped(byte[] imageBytes) {
                @Override
                public void onBitmapCropped(byte[] imageBytes, Rect hint) {
                    Bitmap thumb = null;
                    Point thumbSize = getDefaultThumbnailSize(a.getResources());
                    if (imageBytes != null) {
                        // rotation is set to 0 since imageBytes has already been correctly rotated
                    Bitmap thumb = createThumbnail(
                        thumb = createThumbnail(
                                thumbSize, null, null, imageBytes, null, 0, 0, true);
                        a.getSavedImages().writeImage(thumb, imageBytes);
                    } else {
                        try {
                            // Generate thumb
                            Point size = getDefaultThumbnailSize(a.getResources());
                            Rect finalCropped = new Rect();
                            Utils.getMaxCropRect(hint.width(), hint.height(), size.x, size.y, false)
                                    .roundOut(finalCropped);
                            finalCropped.offset(hint.left, hint.top);

                            InputStream in = a.getContentResolver().openInputStream(mUri);
                            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(in, true);

                            BitmapFactory.Options options = new BitmapFactory.Options();
                            options.inSampleSize = finalCropped.width() / size.x;
                            thumb = decoder.decodeRegion(finalCropped, options);
                            decoder.recycle();
                            Utils.closeSilently(in);
                            if (thumb != null) {
                                thumb = Bitmap.createScaledBitmap(thumb, size.x, size.y, true);
                            }
                        } catch (IOException e) { }
                        PointF center = a.mCropView.getCenter();

                        Float[] extras = new Float[] {
                                a.mCropView.getScale(),
                                center.x,
                                center.y
                        };
                        a.getSavedImages().writeImage(thumb, mUri, extras);
                    }
                }
            };
            boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
@@ -196,7 +233,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
    }

    public static class FileWallpaperInfo extends WallpaperTileInfo {
        private File mFile;
        protected File mFile;

        public FileWallpaperInfo(File target, Drawable thumb) {
            mFile = target;
@@ -207,7 +244,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
            a.setWallpaperButtonEnabled(false);
            final BitmapRegionTileSource.UriBitmapSource bitmapSource =
                    new BitmapRegionTileSource.UriBitmapSource(a.getContext(), Uri.fromFile(mFile));
            a.setCropViewTileSource(bitmapSource, false, true, null, new Runnable() {
            a.setCropViewTileSource(bitmapSource, false, true, getCropViewScaleAndOffsetProvider(),
                    new Runnable() {

                @Override
                public void run() {
@@ -217,6 +255,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
                }
            });
        }

        protected CropViewScaleAndOffsetProvider getCropViewScaleAndOffsetProvider() {
            return null;
        }

        @Override
        public void onSave(WallpaperPickerActivity a) {
            boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
@@ -303,18 +346,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
            LoadRequest req = new LoadRequest();
            req.moveToLeft = false;
            req.touchEnabled = false;
            req.scaleAndOffsetProvider = new CropViewScaleAndOffsetProvider() {

                @Override
                public float getScale(Point wallpaperSize, RectF crop) {
                    return 1f;
                }

                @Override
                public float getParallaxOffset() {
                    return 0.5f;
                }
            };
            req.scaleAndOffsetProvider = new CropViewScaleAndOffsetProvider();
            req.result = new DrawableTileSource(a.getContext(),
                    defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE);
            a.onLoadRequestComplete(req, true);