BitmapUtils.java revision 93a35b93dc582e38ff8ee5979754a16b4bf4da0c
193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/* 293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Copyright (C) 2013 The Android Open Source Project 393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Licensed under the Apache License, Version 2.0 (the "License"); 593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * you may not use this file except in compliance with the License. 693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * You may obtain a copy of the License at 793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * http://www.apache.org/licenses/LICENSE-2.0 993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 1093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Unless required by applicable law or agreed to in writing, software 1193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * distributed under the License is distributed on an "AS IS" BASIS, 1293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * See the License for the specific language governing permissions and 1493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * limitations under the License. 1593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 1693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpackage com.android.bitmap.util; 1893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Rect; 2093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 2193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpublic abstract class BitmapUtils { 2293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 2393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 2493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Calculate a center-crop rectangle for the given input and output 2593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * parameters. The output rectangle to use is written in the given outRect. 2693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 2793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param srcW the source width 2893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param srcH the source height 2993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param dstW the destination width 3093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param dstH the destination height 3193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param dstSliceH the height extent (in destination coordinates) to 3293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * exclude when cropping. You would typically pass dstH, unless 3393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * you are trying to normalize different items to the same 3493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * vertical crop range. 3593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param sampleSize a scaling factor that rect calculation will only use if 3693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * it's more aggressive than regular scaling 3793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param vertSliceFrac vertical slice fraction determines the vertical 3893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * center point for the crop rect. Range is from [0.0, 1.0]. To 3993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * perform a vertically centered crop, use 0.5. Otherwise, see 4093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * absoluteFrac. 4193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param absoluteFrac determines how the vertSliceFrac affects the vertical 4293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * center point. If this parameter is true, the vertical center 4393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * of the resulting output rectangle will be exactly 4493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * [vertSliceFrac * srcH], with care taken to keep the bounds 4593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * within the source rectangle. If this parameter is false, the 4693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * vertical center will be calculated so that the values of 4793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * vertSliceFrac from 0.0 to 1.0 will linearly cover the entirety 4893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * of the source rectangle. 4993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param verticalMultiplier an optional multiplier that will alter the 5093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * output Rect's aspect ratio to be this much taller in the event 5193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * that y is the limiting dimension 5293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param outRect a Rect to write the resulting crop coordinates into 5393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 5493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public static void calculateCroppedSrcRect(final int srcW, final int srcH, final int dstW, 5593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int dstH, final int dstSliceH, int sampleSize, final float vertSliceFrac, 5693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final boolean absoluteFrac, final float verticalMultiplier, final Rect outRect) { 5793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (sampleSize < 1) { 5893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein sampleSize = 1; 5993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 6093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final float regularScale; 6193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final float wScale = (float) srcW / dstW; 6293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final float hScale = (float) srcH / dstH; 6393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (hScale < wScale) { 6493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein regularScale = hScale / verticalMultiplier; 6593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 6693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein regularScale = wScale; 6793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 6893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 6993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final float scale = Math.min(sampleSize, regularScale); 7093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 7193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcCroppedW = Math.round(dstW * scale); 7293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcCroppedH = Math.round(dstH * scale); 7393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcCroppedSliceH = Math.round(dstSliceH * scale); 7493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcHalfSliceH = Math.min(srcCroppedSliceH, srcH) / 2; 7593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 7693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.left = (srcW - srcCroppedW) / 2; 7793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.right = outRect.left + srcCroppedW; 7893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 7993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int centerV; 8093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (absoluteFrac) { 8193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int minCenterV = srcHalfSliceH; 8293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int maxCenterV = srcH - srcHalfSliceH; 8393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein centerV = Math.max(minCenterV, Math.min(maxCenterV, Math.round(srcH * vertSliceFrac))); 8493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 8593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein centerV = Math 8693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein .round(Math.abs(srcH - srcCroppedSliceH) * vertSliceFrac + srcHalfSliceH); 8793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 8893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 8993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.top = centerV - srcCroppedH / 2; 9093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.bottom = outRect.top + srcCroppedH; 9193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 9293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 9393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 9493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param srcW 9593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param srcH 9693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param dstW 9793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param dstH 9893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * @param outRect 9993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 10093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public static void calculateCroppedSrcRect(int srcW, int srcH, int dstW, int dstH, 10193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Rect outRect) { 10293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein calculateCroppedSrcRect(srcW, srcH, dstW, dstH, Integer.MAX_VALUE, outRect); 10393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 10493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 10593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public static void calculateCroppedSrcRect(int srcW, int srcH, int dstW, int dstH, 10693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein int sampleSize, Rect outRect) { 10793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (sampleSize < 1) { 10893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein sampleSize = 1; 10993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 11093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final float regularScale = Math.min( 11193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein (float) srcW / dstW, 11293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein (float) srcH / dstH); 11393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 11493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final float scale = Math.min(sampleSize, regularScale); 11593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 11693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcCroppedW = Math.round(dstW * scale); 11793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcCroppedH = Math.round(dstH * scale); 11893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 11993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.left = (srcW - srcCroppedW) / 2; 12093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.right = outRect.left + srcCroppedW; 12193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 12293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.top = (srcH - srcCroppedH) / 2; 12393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein outRect.bottom = outRect.top + srcCroppedH; 12493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 12593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein} 126