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    /**
243a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung     * Calculate a rectangle for the given input and output parameters. The output
253a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung     * 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
373a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung     * @param horizSliceFrac horizontal slice fraction determines the horizontal
383a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung     *            center point for the crop rect. Range is from [0.0, 1.0]. To
393a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung     *            perform a horizontally centered crop, use 0.5.
4093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param vertSliceFrac vertical slice fraction determines the vertical
4193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            center point for the crop rect. Range is from [0.0, 1.0]. To
4293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            perform a vertically centered crop, use 0.5. Otherwise, see
4393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            absoluteFrac.
4493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param absoluteFrac determines how the vertSliceFrac affects the vertical
4593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            center point. If this parameter is true, the vertical center
4693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            of the resulting output rectangle will be exactly
4793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            [vertSliceFrac * srcH], with care taken to keep the bounds
4893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            within the source rectangle. If this parameter is false, the
4993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            vertical center will be calculated so that the values of
5093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            vertSliceFrac from 0.0 to 1.0 will linearly cover the entirety
5193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            of the source rectangle.
5293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param verticalMultiplier an optional multiplier that will alter the
5393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            output Rect's aspect ratio to be this much taller in the event
5493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     *            that y is the limiting dimension
5593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param outRect a Rect to write the resulting crop coordinates into
5693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     */
5793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public static void calculateCroppedSrcRect(final int srcW, final int srcH, final int dstW,
583a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung            final int dstH, final int dstSliceH, int sampleSize, final float horizSliceFrac,
593a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung            final float vertSliceFrac, final boolean absoluteFrac, final float verticalMultiplier,
603a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung            final Rect outRect) {
6193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (sampleSize < 1) {
6293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            sampleSize = 1;
6393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
6493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final float regularScale;
6593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final float wScale = (float) srcW / dstW;
6693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final float hScale = (float) srcH / dstH;
6793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (hScale < wScale) {
6893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            regularScale = hScale / verticalMultiplier;
6993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        } else {
7093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            regularScale = wScale;
7193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
7293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
7393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final float scale = Math.min(sampleSize, regularScale);
7493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
7593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int srcCroppedW = Math.round(dstW * scale);
7693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int srcCroppedH = Math.round(dstH * scale);
7793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int srcCroppedSliceH = Math.round(dstSliceH * scale);
7893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int srcHalfSliceH = Math.min(srcCroppedSliceH, srcH) / 2;
7993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
803a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung        outRect.left = (int) (horizSliceFrac * (srcW - srcCroppedW));
8193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        outRect.right = outRect.left + srcCroppedW;
8293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
8393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int centerV;
8493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (absoluteFrac) {
8593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            final int minCenterV = srcHalfSliceH;
8693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            final int maxCenterV = srcH - srcHalfSliceH;
8793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            centerV = Math.max(minCenterV, Math.min(maxCenterV, Math.round(srcH * vertSliceFrac)));
8893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        } else {
8993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            centerV = Math
9093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    .round(Math.abs(srcH - srcCroppedSliceH) * vertSliceFrac + srcHalfSliceH);
9193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
9293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
9393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        outRect.top = centerV - srcCroppedH / 2;
9493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        outRect.bottom = outRect.top + srcCroppedH;
9593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
9693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
9793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    /**
9893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param srcW
9993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param srcH
10093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param dstW
10193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param dstH
10293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param outRect
10393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     */
10493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public static void calculateCroppedSrcRect(int srcW, int srcH, int dstW, int dstH,
10593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            Rect outRect) {
10693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        calculateCroppedSrcRect(srcW, srcH, dstW, dstH, Integer.MAX_VALUE, outRect);
10793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
10893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
10993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public static void calculateCroppedSrcRect(int srcW, int srcH, int dstW, int dstH,
11093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            int sampleSize, Rect outRect) {
11193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (sampleSize < 1) {
11293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            sampleSize = 1;
11393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
11493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final float regularScale = Math.min(
11593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                (float) srcW / dstW,
11693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                (float) srcH / dstH);
11793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
11893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final float scale = Math.min(sampleSize, regularScale);
11993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
12093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int srcCroppedW = Math.round(dstW * scale);
12193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int srcCroppedH = Math.round(dstH * scale);
12293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
12393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        outRect.left = (srcW - srcCroppedW) / 2;
12493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        outRect.right = outRect.left + srcCroppedW;
12593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
12693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        outRect.top = (srcH - srcCroppedH) / 2;
12793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        outRect.bottom = outRect.top + srcCroppedH;
12893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
12993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein}
130