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