1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.car.apps.common; 17 18 import android.graphics.Bitmap; 19 import android.util.Log; 20 21 public class BitmapUtils { 22 private static final String TAG = "BitmapUtils"; 23 24 /** 25 * Scales a bitmap while preserving the proportions such that both dimensions are the smallest 26 * values possible that are equal to or larger than the given dimensions. 27 * 28 * This function can be a few times as expensive as Bitmap.createScaledBitmap with 29 * filtering when downscaling, but it produces much nicer results. 30 * 31 * @param bm The bitmap to scale. 32 * @param width The desired width. 33 * @param height The desired height. 34 * @return The scaled bitmap, or the original bitmap if scaling was not necessary. 35 */ 36 public static Bitmap scaleBitmap(Bitmap bm, int width, int height) { 37 if (bm == null || (bm.getHeight() == height && bm.getWidth() == width)) { 38 return bm; 39 } 40 41 float heightScale = 1f; 42 if (bm.getHeight() > height) { 43 heightScale = (float) height / bm.getHeight(); 44 } 45 float widthScale = 1f; 46 if (bm.getWidth() > width) { 47 widthScale = (float) width / bm.getWidth(); 48 } 49 float scale = heightScale > widthScale ? heightScale : widthScale; 50 int scaleWidth = (int) Math.ceil(bm.getWidth() * scale); 51 int scaleHeight = (int) Math.ceil(bm.getHeight() * scale); 52 53 Bitmap scaledBm = bm; 54 // If you try to scale an image down too much in one go, you can end up with discontinuous 55 // interpolation. Therefore, if necessary, we scale the image to twice the desired size 56 // and do a second scaling to the desired size, which smooths jaggedness from the first go. 57 if (scale < .5f) { 58 scaledBm = Bitmap.createScaledBitmap(scaledBm, scaleWidth * 2, scaleHeight * 2, true); 59 } 60 61 if (scale != 1f) { 62 Bitmap newScaledBitmap = Bitmap 63 .createScaledBitmap(scaledBm, scaleWidth, scaleHeight, true); 64 if (scaledBm != bm) { 65 scaledBm.recycle(); 66 } 67 scaledBm = newScaledBitmap; 68 } 69 return scaledBm; 70 } 71 72 /** 73 * Crops the given bitmap to a centered rectangle of the given dimensions. 74 * 75 * @param bm the bitmap to crop. 76 * @param width the width to crop to. 77 * @param height the height to crop to. 78 * @return The cropped bitmap, or the original if no cropping was necessary. 79 */ 80 public static Bitmap cropBitmap(Bitmap bm, int width, int height) { 81 if (bm == null) { 82 return bm; 83 } 84 if (bm.getHeight() < height || bm.getWidth() < width) { 85 if (Log.isLoggable(TAG, Log.INFO)) { 86 Log.i(TAG, String.format( 87 "Can't crop bitmap to larger dimensions (%d, %d) -> (%d, %d).", 88 bm.getWidth(), bm.getHeight(), width, height)); 89 } 90 return bm; 91 } 92 int x = (bm.getWidth() - width) / 2; 93 int y =(bm.getHeight() - height) / 2; 94 return Bitmap.createBitmap(bm, x, y, width, height); 95 } 96 } 97