333 lines
13 KiB
Java
333 lines
13 KiB
Java
/*
|
|
* Copyright (C) 2013-2014 The CyanogenMod 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 org.cyanogenmod.internal.util;
|
|
|
|
import android.app.WallpaperManager;
|
|
import android.content.Context;
|
|
import android.content.res.AssetManager;
|
|
import android.database.Cursor;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
import android.graphics.Point;
|
|
import android.net.Uri;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
import android.webkit.URLUtil;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.InputStream;
|
|
|
|
import cyanogenmod.providers.ThemesContract.PreviewColumns;
|
|
import cyanogenmod.providers.ThemesContract.ThemesColumns;
|
|
|
|
import libcore.io.IoUtils;
|
|
|
|
public class ImageUtils {
|
|
private static final String TAG = ImageUtils.class.getSimpleName();
|
|
|
|
private static final String ASSET_URI_PREFIX = "file:///android_asset/";
|
|
private static final int DEFAULT_IMG_QUALITY = 100;
|
|
|
|
/**
|
|
* Gets the Width and Height of the image
|
|
*
|
|
* @param inputStream The input stream of the image
|
|
*
|
|
* @return A point structure that holds the Width and Height (x and y)/*"
|
|
*/
|
|
public static Point getImageDimension(InputStream inputStream) {
|
|
if (inputStream == null) {
|
|
throw new IllegalArgumentException("'inputStream' cannot be null!");
|
|
}
|
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
|
options.inJustDecodeBounds = true;
|
|
BitmapFactory.decodeStream(inputStream, null, options);
|
|
Point point = new Point(options.outWidth,options.outHeight);
|
|
return point;
|
|
}
|
|
|
|
/**
|
|
* Crops the input image and returns a new InputStream of the cropped area
|
|
*
|
|
* @param inputStream The input stream of the image
|
|
* @param imageWidth Width of the input image
|
|
* @param imageHeight Height of the input image
|
|
* @param inputStream Desired Width
|
|
* @param inputStream Desired Width
|
|
*
|
|
* @return a new InputStream of the cropped area/*"
|
|
*/
|
|
public static InputStream cropImage(InputStream inputStream, int imageWidth, int imageHeight,
|
|
int outWidth, int outHeight) throws IllegalArgumentException {
|
|
if (inputStream == null){
|
|
throw new IllegalArgumentException("inputStream cannot be null");
|
|
}
|
|
|
|
if (imageWidth <= 0 || imageHeight <= 0) {
|
|
throw new IllegalArgumentException(
|
|
String.format("imageWidth and imageHeight must be > 0: imageWidth=%d" +
|
|
" imageHeight=%d", imageWidth, imageHeight));
|
|
}
|
|
|
|
if (outWidth <= 0 || outHeight <= 0) {
|
|
throw new IllegalArgumentException(
|
|
String.format("outWidth and outHeight must be > 0: outWidth=%d" +
|
|
" outHeight=%d", imageWidth, outHeight));
|
|
}
|
|
|
|
int scaleDownSampleSize = Math.min(imageWidth / outWidth, imageHeight / outHeight);
|
|
if (scaleDownSampleSize > 0) {
|
|
imageWidth /= scaleDownSampleSize;
|
|
imageHeight /= scaleDownSampleSize;
|
|
} else {
|
|
float ratio = (float) outWidth / outHeight;
|
|
if (imageWidth < imageHeight * ratio) {
|
|
outWidth = imageWidth;
|
|
outHeight = (int) (outWidth / ratio);
|
|
} else {
|
|
outHeight = imageHeight;
|
|
outWidth = (int) (outHeight * ratio);
|
|
}
|
|
}
|
|
int left = (imageWidth - outWidth) / 2;
|
|
int top = (imageHeight - outHeight) / 2;
|
|
InputStream compressed = null;
|
|
try {
|
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
|
if (scaleDownSampleSize > 1) {
|
|
options.inSampleSize = scaleDownSampleSize;
|
|
}
|
|
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
|
|
if (bitmap == null) {
|
|
return null;
|
|
}
|
|
Bitmap cropped = Bitmap.createBitmap(bitmap, left, top, outWidth, outHeight);
|
|
ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
|
|
if (cropped.compress(Bitmap.CompressFormat.PNG, DEFAULT_IMG_QUALITY, tmpOut)) {
|
|
byte[] outByteArray = tmpOut.toByteArray();
|
|
compressed = new ByteArrayInputStream(outByteArray);
|
|
}
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "Exception " + e);
|
|
}
|
|
return compressed;
|
|
}
|
|
|
|
/**
|
|
* Crops the lock screen image and returns a new InputStream of the cropped area
|
|
*
|
|
* @param pkgName Name of the theme package
|
|
* @param context The context
|
|
*
|
|
* @return a new InputStream of the cropped image/*"
|
|
*/
|
|
public static InputStream getCroppedKeyguardStream(String pkgName, Context context)
|
|
throws IllegalArgumentException {
|
|
if (TextUtils.isEmpty(pkgName)) {
|
|
throw new IllegalArgumentException("'pkgName' cannot be null or empty!");
|
|
}
|
|
if (context == null) {
|
|
throw new IllegalArgumentException("'context' cannot be null!");
|
|
}
|
|
|
|
InputStream cropped = null;
|
|
InputStream stream = null;
|
|
try {
|
|
stream = getOriginalKeyguardStream(pkgName, context);
|
|
if (stream == null) {
|
|
return null;
|
|
}
|
|
Point point = getImageDimension(stream);
|
|
IoUtils.closeQuietly(stream);
|
|
if (point == null || point.x == 0 || point.y == 0) {
|
|
return null;
|
|
}
|
|
WallpaperManager wm = WallpaperManager.getInstance(context);
|
|
int outWidth = wm.getDesiredMinimumWidth();
|
|
int outHeight = wm.getDesiredMinimumHeight();
|
|
stream = getOriginalKeyguardStream(pkgName, context);
|
|
if (stream == null) {
|
|
return null;
|
|
}
|
|
cropped = cropImage(stream, point.x, point.y, outWidth, outHeight);
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "Exception " + e);
|
|
} finally {
|
|
IoUtils.closeQuietly(stream);
|
|
}
|
|
return cropped;
|
|
}
|
|
|
|
/**
|
|
* Crops the wallpaper image and returns a new InputStream of the cropped area
|
|
*
|
|
* @param pkgName Name of the theme package
|
|
* @param context The context
|
|
*
|
|
* @return a new InputStream of the cropped image/*"
|
|
*/
|
|
public static InputStream getCroppedWallpaperStream(String pkgName, long wallpaperId,
|
|
Context context) {
|
|
if (TextUtils.isEmpty(pkgName)) {
|
|
throw new IllegalArgumentException("'pkgName' cannot be null or empty!");
|
|
}
|
|
if (context == null) {
|
|
throw new IllegalArgumentException("'context' cannot be null!");
|
|
}
|
|
|
|
InputStream cropped = null;
|
|
InputStream stream = null;
|
|
try {
|
|
stream = getOriginalWallpaperStream(pkgName, wallpaperId, context);
|
|
if (stream == null) {
|
|
return null;
|
|
}
|
|
Point point = getImageDimension(stream);
|
|
IoUtils.closeQuietly(stream);
|
|
if (point == null || point.x == 0 || point.y == 0) {
|
|
return null;
|
|
}
|
|
WallpaperManager wm = WallpaperManager.getInstance(context);
|
|
int outWidth = wm.getDesiredMinimumWidth();
|
|
int outHeight = wm.getDesiredMinimumHeight();
|
|
stream = getOriginalWallpaperStream(pkgName, wallpaperId, context);
|
|
if (stream == null) {
|
|
return null;
|
|
}
|
|
cropped = cropImage(stream, point.x, point.y, outWidth, outHeight);
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "Exception " + e);
|
|
} finally {
|
|
IoUtils.closeQuietly(stream);
|
|
}
|
|
return cropped;
|
|
}
|
|
|
|
private static InputStream getOriginalKeyguardStream(String pkgName, Context context) {
|
|
if (TextUtils.isEmpty(pkgName) || context == null) {
|
|
return null;
|
|
}
|
|
|
|
InputStream inputStream = null;
|
|
try {
|
|
//Get input WP stream from the theme
|
|
Context themeCtx = context.createPackageContext(pkgName,
|
|
Context.CONTEXT_IGNORE_SECURITY);
|
|
AssetManager assetManager = themeCtx.getAssets();
|
|
String wpPath = ThemeUtils.getLockscreenWallpaperPath(assetManager);
|
|
if (wpPath == null) {
|
|
Log.w(TAG, "Not setting lockscreen wp because wallpaper file was not found.");
|
|
} else {
|
|
inputStream = ThemeUtils.getInputStreamFromAsset(themeCtx,
|
|
ASSET_URI_PREFIX + wpPath);
|
|
}
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "There was an error setting lockscreen wp for pkg " + pkgName, e);
|
|
}
|
|
return inputStream;
|
|
}
|
|
|
|
private static InputStream getOriginalWallpaperStream(String pkgName, long componentId,
|
|
Context context) {
|
|
String wpPath;
|
|
if (TextUtils.isEmpty(pkgName) || context == null) {
|
|
return null;
|
|
}
|
|
|
|
InputStream inputStream = null;
|
|
String selection = ThemesColumns.PKG_NAME + "= ?";
|
|
String[] selectionArgs = {pkgName};
|
|
Cursor c = context.getContentResolver().query(ThemesColumns.CONTENT_URI,
|
|
null, selection,
|
|
selectionArgs, null);
|
|
if (c == null || c.getCount() < 1) {
|
|
if (c != null) c.close();
|
|
return null;
|
|
} else {
|
|
c.moveToFirst();
|
|
}
|
|
|
|
try {
|
|
Context themeContext = context.createPackageContext(pkgName,
|
|
Context.CONTEXT_IGNORE_SECURITY);
|
|
boolean isLegacyTheme = c.getInt(
|
|
c.getColumnIndex(ThemesColumns.IS_LEGACY_THEME)) == 1;
|
|
String wallpaper = c.getString(
|
|
c.getColumnIndex(ThemesColumns.WALLPAPER_URI));
|
|
if (wallpaper != null) {
|
|
if (URLUtil.isAssetUrl(wallpaper)) {
|
|
inputStream = ThemeUtils.getInputStreamFromAsset(themeContext, wallpaper);
|
|
} else {
|
|
inputStream = context.getContentResolver().openInputStream(
|
|
Uri.parse(wallpaper));
|
|
}
|
|
} else {
|
|
// try and get the wallpaper directly from the apk if the URI was null
|
|
Context themeCtx = context.createPackageContext(pkgName,
|
|
Context.CONTEXT_IGNORE_SECURITY);
|
|
AssetManager assetManager = themeCtx.getAssets();
|
|
wpPath = queryWpPathFromComponentId(context, pkgName, componentId);
|
|
if (wpPath == null) wpPath = ThemeUtils.getWallpaperPath(assetManager);
|
|
if (wpPath == null) {
|
|
Log.e(TAG, "Not setting wp because wallpaper file was not found.");
|
|
} else {
|
|
inputStream = ThemeUtils.getInputStreamFromAsset(themeCtx,
|
|
ASSET_URI_PREFIX + wpPath);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "getWallpaperStream: " + e);
|
|
} finally {
|
|
c.close();
|
|
}
|
|
|
|
return inputStream;
|
|
}
|
|
|
|
private static String queryWpPathFromComponentId(Context context, String pkgName,
|
|
long componentId) {
|
|
String wpPath = null;
|
|
String[] projection = new String[] { PreviewColumns.COL_VALUE };
|
|
String selection = ThemesColumns.PKG_NAME + "=? AND " +
|
|
PreviewColumns.COMPONENT_ID + "=? AND " +
|
|
PreviewColumns.COL_KEY + "=?";
|
|
String[] selectionArgs = new String[] {
|
|
pkgName,
|
|
Long.toString(componentId),
|
|
PreviewColumns.WALLPAPER_FULL
|
|
};
|
|
|
|
Cursor c = context.getContentResolver()
|
|
.query(PreviewColumns.COMPONENTS_URI,
|
|
projection, selection, selectionArgs, null);
|
|
if (c != null) {
|
|
try {
|
|
if (c.moveToFirst()) {
|
|
int valIdx = c.getColumnIndex(PreviewColumns.COL_VALUE);
|
|
wpPath = c.getString(valIdx);
|
|
}
|
|
} catch(Exception e) {
|
|
Log.e(TAG, "Could not get wallpaper path", e);
|
|
} finally {
|
|
c.close();
|
|
}
|
|
}
|
|
return wpPath;
|
|
}
|
|
}
|
|
|