From 52f62a43fbe52ac62114501926c65ac955690a8c Mon Sep 17 00:00:00 2001 From: Clark Scheff Date: Wed, 21 May 2014 13:45:08 -0700 Subject: Standardize preview images. Themes can contain a preview image for wallpaper, lockscreen, and styles. These can be either .png or .jpg and use the following naming conventions: wallpaper -> assets/images/wallpaper_preview.[png|jpg] lockscreen -> assets/images/lockscreen_preview.[png|jpg] styles -> assets/images/styles_preview.[png|jpg] Change-Id: Ibe441abf941e8b995c94eb43f6c6f237758d914b --- .../cyanogenmod/themes/provider/BitmapUtils.java | 92 ++++++++++++++++++++++ .../themes/provider/CopyImageService.java | 59 ++++++++------ 2 files changed, 127 insertions(+), 24 deletions(-) create mode 100644 src/org/cyanogenmod/themes/provider/BitmapUtils.java (limited to 'src') diff --git a/src/org/cyanogenmod/themes/provider/BitmapUtils.java b/src/org/cyanogenmod/themes/provider/BitmapUtils.java new file mode 100644 index 0000000..4a49068 --- /dev/null +++ b/src/org/cyanogenmod/themes/provider/BitmapUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 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.themes.provider; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.util.Log; + +import java.io.Closeable; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public class BitmapUtils { + private static final String TAG = "BitmapUtils"; + private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5; + + /** + * Returns the bitmap from the given uri loaded using the given options. + * Returns null on failure. + */ + public static Bitmap loadBitmap(Context context, InputStream is, BitmapFactory.Options o) { + try { + return BitmapFactory.decodeStream(is, null, o); + } finally { + closeSilently(is); + } + } + + /** + * Loads a bitmap that has been downsampled using sampleSize from a given url. + */ + public static Bitmap loadDownsampledBitmap(Context context, InputStream is, int sampleSize) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inMutable = true; + options.inSampleSize = sampleSize; + return loadBitmap(context, is, options); + } + + /** + * Loads a bitmap that is downsampled by at least the input sample size. In + * low-memory situations, the bitmap may be downsampled further. + */ + public static Bitmap loadBitmapWithBackouts(Context context, InputStream is, int sampleSize) { + boolean noBitmap = true; + int num_tries = 0; + if (sampleSize <= 0) { + sampleSize = 1; + } + Bitmap bmap = null; + while (noBitmap) { + try { + // Try to decode, downsample if low-memory. + bmap = loadDownsampledBitmap(context, is, sampleSize); + noBitmap = false; + } catch (java.lang.OutOfMemoryError e) { + // Try with more downsampling before failing for good. + if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { + throw e; + } + bmap = null; + System.gc(); + sampleSize *= 2; + } + } + return bmap; + } + + public static void closeSilently(Closeable c) { + if (c == null) return; + try { + c.close(); + } catch (IOException t) { + Log.w(TAG, "close fail ", t); + } + } +} diff --git a/src/org/cyanogenmod/themes/provider/CopyImageService.java b/src/org/cyanogenmod/themes/provider/CopyImageService.java index 33c6954..e98fa03 100644 --- a/src/org/cyanogenmod/themes/provider/CopyImageService.java +++ b/src/org/cyanogenmod/themes/provider/CopyImageService.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetManager; +import android.graphics.Bitmap; import android.net.Uri; import android.os.Environment; import android.provider.ThemesContract.ThemesColumns; @@ -45,6 +46,13 @@ public class CopyImageService extends IntentService { private static final String WALLPAPER_PATH = "/data/org.cyanogenmod.themes.provider/files/wallpapers/"; + private static final String WALLPAPER_PREVIEW = "images/wallpaper_preview"; + private static final String LOCKSCREEN_PREVIEW = "images/lockscreen_preview"; + private static final String STYLES_PREVIEW = "images/styles_preview"; + + private static final String EXT_JPG = ".jpg"; + private static final String EXT_PNG = ".png"; + public CopyImageService() { super(CopyImageService.class.getName()); } @@ -63,10 +71,10 @@ public class CopyImageService extends IntentService { String homescreen = Environment.getDataDirectory().getPath() + IMAGES_PATH + pkgName - + ".homescreen.png"; + + ".homescreen.jpg"; String lockscreen = Environment.getDataDirectory().getPath() + IMAGES_PATH + pkgName - + ".lockscreen.png"; + + ".lockscreen.jpg"; String stylePreview = Environment.getDataDirectory().getPath() + IMAGES_PATH + pkgName + ".stylepreview.jpg"; @@ -106,10 +114,9 @@ public class CopyImageService extends IntentService { // internal storage AssetManager assetManager = themeContext.getAssets(); try { - InputStream homescreen = assetManager - .open("images/icons_wallpaper_straight.png"); - InputStream lockscreen = assetManager - .open("images/lockscreen_portrait.png"); + InputStream homescreen = getPreviewAsset(assetManager, WALLPAPER_PREVIEW); + + InputStream lockscreen = getPreviewAsset(assetManager, LOCKSCREEN_PREVIEW); File dataDir = context.getFilesDir(); // Environment.getDataDirectory(); File imgDir = new File(dataDir, "images"); @@ -117,45 +124,49 @@ public class CopyImageService extends IntentService { imgDir.mkdir(); wpDir.mkdir(); - File homescreenOut = new File(imgDir, pkgName + ".homescreen.png"); - File lockscreenOut = new File(imgDir, pkgName + ".lockscreen.png"); + File homescreenOut = new File(imgDir, pkgName + ".homescreen.jpg"); + File lockscreenOut = new File(imgDir, pkgName + ".lockscreen.jpg"); FileOutputStream out = new FileOutputStream(homescreenOut); - byte[] buffer = new byte[4096]; - int count = 0; - while ((count = homescreen.read(buffer)) != -1) { - out.write(buffer, 0, count); - } + Bitmap bmp = BitmapUtils.loadBitmapWithBackouts(context, homescreen, 1); + bmp.compress(Bitmap.CompressFormat.JPEG, 90, out); out.close(); out = new FileOutputStream(lockscreenOut); - while ((count = lockscreen.read(buffer)) != -1) { - out.write(buffer, 0, count); - } + bmp = BitmapUtils.loadBitmapWithBackouts(context, lockscreen, 1); + bmp.compress(Bitmap.CompressFormat.JPEG, 90, out); out.close(); } catch (IOException e) { - Log.e(TAG, "ThemesOpenHelper could not copy test image data"); + Log.e(TAG, "ThemesOpenHelper could not copy preview image"); } //Copy Style preview try { - InputStream stylepreview = assetManager - .open("images/style.jpg"); + InputStream stylepreview = getPreviewAsset(assetManager, STYLES_PREVIEW); File dataDir = context.getFilesDir(); File imgDir = new File(dataDir, "images"); imgDir.mkdir(); File styleOut = new File(imgDir, pkgName + ".stylepreview.jpg"); - byte[] buffer = new byte[4096]; - int count = 0; FileOutputStream out = new FileOutputStream(styleOut); - while ((count = stylepreview.read(buffer)) != -1) { - out.write(buffer, 0, count); - } + Bitmap bmp = BitmapUtils.loadBitmapWithBackouts(context, stylepreview, 1); + bmp.compress(Bitmap.CompressFormat.JPEG, 90, out); out.close(); } catch (IOException e) { Log.e(TAG, "ThemesOpenHelper could not copy style image data"); } } + + private static InputStream getPreviewAsset(AssetManager am, String preview) throws IOException { + InputStream is = null; + try { + is = am.open(preview + EXT_JPG); + } catch (IOException e) { + // we'll try and fallback to PNG + } + if (is == null) is = am.open(preview + EXT_PNG); + + return is; + } } -- cgit v1.2.3