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
17package com.android.bitmap.util;
18
19import android.graphics.Rect;
20
21public 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     * @param srcW
95     * @param srcH
96     * @param dstW
97     * @param dstH
98     * @param outRect
99     */
100    public static void calculateCroppedSrcRect(int srcW, int srcH, int dstW, int dstH,
101            Rect outRect) {
102        calculateCroppedSrcRect(srcW, srcH, dstW, dstH, Integer.MAX_VALUE, outRect);
103    }
104
105    public static void calculateCroppedSrcRect(int srcW, int srcH, int dstW, int dstH,
106            int sampleSize, Rect outRect) {
107        if (sampleSize < 1) {
108            sampleSize = 1;
109        }
110        final float regularScale = Math.min(
111                (float) srcW / dstW,
112                (float) srcH / dstH);
113
114        final float scale = Math.min(sampleSize, regularScale);
115
116        final int srcCroppedW = Math.round(dstW * scale);
117        final int srcCroppedH = Math.round(dstH * scale);
118
119        outRect.left = (srcW - srcCroppedW) / 2;
120        outRect.right = outRect.left + srcCroppedW;
121
122        outRect.top = (srcH - srcCroppedH) / 2;
123        outRect.bottom = outRect.top + srcCroppedH;
124    }
125}
126