1 /*
2  * Copyright (C) 2023 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.google.android.wallpaper.weathereffects.graphics.utils
18 
19 /** Contains offsets and scales to position image inside a surface. */
20 class ImageCrop(
21     /**
22      * The left start of the image relatively to the left edge of the surface that will contain the
23      * image.
24      */
25     val leftOffset: Float = 0f,
26     /**
27      * The top distance start of the image relatively to the top edge of the surface that will
28      * contain the image.
29      */
30     val topOffset: Float = 0f,
31     /** The horizontal scale applied to the image. */
32     val horizontalScale: Float = 1f,
33     /** The vertical scale applied to the image. */
34     val verticalScale: Float = 1f,
35 ) {
36 
37     companion object {
38 
39         /**
40          * Calculates the [ImageCrop] that would make the image cover the surface (that is, the
41          * image will be scaled to the smallest possible size so it fills the container, preserving
42          * the aspect ratio and cropping the image vertically or horizontally if necessary) and
43          * center its content.
44          *
45          * @param surfaceWidth the width of the surface where the image will be displayed.
46          * @param surfaceWidth the height of the surface where the image will be displayed.
47          * @param imageWidth the width of the image that we want to display.
48          * @param imageHeight the height of the image that we want to display.
49          * @return the [ImageCrop] that will center cover the image into the surface.
50          */
centerCoverCropnull51         fun centerCoverCrop(
52             surfaceWidth: Float,
53             surfaceHeight: Float,
54             imageWidth: Float,
55             imageHeight: Float
56         ): ImageCrop {
57             val uvScaleHeight: Float = imageHeight / surfaceHeight
58             val uvScaleWidth: Float = imageWidth / surfaceWidth
59 
60             val uvScale =
61                 if (imageWidth / imageHeight > surfaceWidth / surfaceHeight) {
62                     uvScaleHeight
63                 } else {
64                     uvScaleWidth
65                 }
66 
67             val horizontalOffset = (imageWidth - surfaceWidth * uvScale) / 2f
68             val verticalOffset = (imageHeight - surfaceHeight * uvScale) / 2f
69 
70             return ImageCrop(horizontalOffset, verticalOffset, uvScale, uvScale)
71         }
72     }
73 }
74