12c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer/*
22c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * Copyright (C) 2016 The Android Open Source Project
32c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer *
42c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * Licensed under the Apache License, Version 2.0 (the "License");
52c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * you may not use this file except in compliance with the License.
62c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * You may obtain a copy of the License at
72c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer *
82c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer *      http://www.apache.org/licenses/LICENSE-2.0
92c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer *
102c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * Unless required by applicable law or agreed to in writing, software
112c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * distributed under the License is distributed on an "AS IS" BASIS,
122c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * See the License for the specific language governing permissions and
142c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer * limitations under the License.
152c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer */
162c9394097967d01f79f76148bbaebed5324a529fRakesh Iyerpackage com.android.car.apps.common;
172c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer
182c9394097967d01f79f76148bbaebed5324a529fRakesh Iyerimport android.graphics.Bitmap;
192c9394097967d01f79f76148bbaebed5324a529fRakesh Iyerimport android.util.Log;
202c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer
212c9394097967d01f79f76148bbaebed5324a529fRakesh Iyerpublic class BitmapUtils {
222c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer    private static final String TAG = "BitmapUtils";
232c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer
242c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer    /**
252c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * Scales a bitmap while preserving the proportions such that both dimensions are the smallest
262c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * values possible that are equal to or larger than the given dimensions.
272c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     *
282c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * This function can be a few times as expensive as Bitmap.createScaledBitmap with
292c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * filtering when downscaling, but it produces much nicer results.
302c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     *
312c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @param bm The bitmap to scale.
322c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @param width The desired width.
332c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @param height The desired height.
342c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @return The scaled bitmap, or the original bitmap if scaling was not necessary.
352c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     */
362c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer    public static Bitmap scaleBitmap(Bitmap bm, int width, int height) {
372c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        if (bm == null || (bm.getHeight() == height && bm.getWidth() == width)) {
382c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            return bm;
392c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        }
402c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer
412c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        float heightScale = 1f;
422c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        if (bm.getHeight() > height) {
432c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            heightScale = (float) height / bm.getHeight();
442c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        }
452c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        float widthScale = 1f;
462c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        if (bm.getWidth() > width) {
472c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            widthScale = (float) width / bm.getWidth();
482c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        }
492c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        float scale = heightScale > widthScale ? heightScale : widthScale;
502c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        int scaleWidth = (int) Math.ceil(bm.getWidth() * scale);
512c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        int scaleHeight = (int) Math.ceil(bm.getHeight() * scale);
522c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer
532c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        Bitmap scaledBm = bm;
542c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        // If you try to scale an image down too much in one go, you can end up with discontinuous
552c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        // interpolation. Therefore, if necessary, we scale the image to twice the desired size
562c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        // and do a second scaling to the desired size, which smooths jaggedness from the first go.
572c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        if (scale < .5f) {
582c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            scaledBm = Bitmap.createScaledBitmap(scaledBm, scaleWidth * 2, scaleHeight * 2, true);
592c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        }
602c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer
612c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        if (scale != 1f) {
622c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            Bitmap newScaledBitmap = Bitmap
632c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer                    .createScaledBitmap(scaledBm, scaleWidth, scaleHeight, true);
642c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            if (scaledBm != bm) {
652c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer                scaledBm.recycle();
662c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            }
672c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            scaledBm = newScaledBitmap;
682c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        }
692c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        return scaledBm;
702c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer    }
712c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer
722c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer    /**
732c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * Crops the given bitmap to a centered rectangle of the given dimensions.
742c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     *
752c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @param bm the bitmap to crop.
762c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @param width the width to crop to.
772c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @param height the height to crop to.
782c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     * @return The cropped bitmap, or the original if no cropping was necessary.
792c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer     */
802c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer    public static Bitmap cropBitmap(Bitmap bm, int width, int height) {
812c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        if (bm == null) {
822c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            return bm;
832c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        }
842c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        if (bm.getHeight() < height || bm.getWidth() < width) {
852c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            if (Log.isLoggable(TAG, Log.INFO)) {
862c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer                Log.i(TAG, String.format(
872c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer                        "Can't crop bitmap to larger dimensions (%d, %d) -> (%d, %d).",
882c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer                        bm.getWidth(), bm.getHeight(), width, height));
892c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            }
902c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer            return bm;
912c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        }
922c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        int x = (bm.getWidth() - width) / 2;
932c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        int y =(bm.getHeight() - height) / 2;
942c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer        return Bitmap.createBitmap(bm, x, y, width, height);
952c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer    }
962c9394097967d01f79f76148bbaebed5324a529fRakesh Iyer}
97