Home | History | Annotate | Download | only in bitmap
      1 /*
      2  * Copyright (C) 2013 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 
     17 package com.android.bitmap;
     18 
     19 import android.graphics.Rect;
     20 
     21 public abstract class BitmapUtils {
     22 
     23     /**
     24      * Calculate a center-crop rectangle for the given input and output
     25      * parameters. The output rectangle to use is written in the given outRect.
     26      *
     27      * @param srcW the source width
     28      * @param srcH the source height
     29      * @param dstW the destination width
     30      * @param dstH the destination height
     31      * @param dstSliceH the height extent (in destination coordinates) to
     32      *            exclude when cropping. You would typically pass dstH, unless
     33      *            you are trying to normalize different items to the same
     34      *            vertical crop range.
     35      * @param sampleSize a scaling factor that rect calculation will only use if
     36      *            it's more aggressive than regular scaling
     37      * @param vertSliceFrac vertical slice fraction determines the vertical
     38      *            center point for the crop rect. Range is from [0.0, 1.0]. To
     39      *            perform a vertically centered crop, use 0.5. Otherwise, see
     40      *            absoluteFrac.
     41      * @param absoluteFrac determines how the vertSliceFrac affects the vertical
     42      *            center point. If this parameter is true, the vertical center
     43      *            of the resulting output rectangle will be exactly
     44      *            [vertSliceFrac * srcH], with care taken to keep the bounds
     45      *            within the source rectangle. If this parameter is false, the
     46      *            vertical center will be calculated so that the values of
     47      *            vertSliceFrac from 0.0 to 1.0 will linearly cover the entirety
     48      *            of the source rectangle.
     49      * @param verticalMultiplier an optional multiplier that will alter the
     50      *            output Rect's aspect ratio to be this much taller in the event
     51      *            that y is the limiting dimension
     52      * @param outRect a Rect to write the resulting crop coordinates into
     53      */
     54     public static void calculateCroppedSrcRect(final int srcW, final int srcH, final int dstW,
     55             final int dstH, final int dstSliceH, int sampleSize, final float vertSliceFrac,
     56             final boolean absoluteFrac, final float verticalMultiplier, final Rect outRect) {
     57         if (sampleSize < 1) {
     58             sampleSize = 1;
     59         }
     60         final float regularScale;
     61         final float wScale = (float) srcW / dstW;
     62         final float hScale = (float) srcH / dstH;
     63         if (hScale < wScale) {
     64             regularScale = hScale / verticalMultiplier;
     65         } else {
     66             regularScale = wScale;
     67         }
     68 
     69         final float scale = Math.min(sampleSize, regularScale);
     70 
     71         final int srcCroppedW = Math.round(dstW * scale);
     72         final int srcCroppedH = Math.round(dstH * scale);
     73         final int srcCroppedSliceH = Math.round(dstSliceH * scale);
     74         final int srcHalfSliceH = Math.min(srcCroppedSliceH, srcH) / 2;
     75 
     76         outRect.left = (srcW - srcCroppedW) / 2;
     77         outRect.right = outRect.left + srcCroppedW;
     78 
     79         final int centerV;
     80         if (absoluteFrac) {
     81             final int minCenterV = srcHalfSliceH;
     82             final int maxCenterV = srcH - srcHalfSliceH;
     83             centerV = Math.max(minCenterV, Math.min(maxCenterV, Math.round(srcH * vertSliceFrac)));
     84         } else {
     85             centerV = Math
     86                     .round(Math.abs(srcH - srcCroppedSliceH) * vertSliceFrac + srcHalfSliceH);
     87         }
     88 
     89         outRect.top = centerV - srcCroppedH / 2;
     90         outRect.bottom = outRect.top + srcCroppedH;
     91     }
     92 
     93 }
     94