replicant-vendor_cmsdk/sdk/src/java/org/cyanogenmod/internal/util/ImageUtils.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;
}
}