1/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
2*
3* Redistribution and use in source and binary forms, with or without
4* modification, are permitted provided that the following conditions are
5* met:
6*     * Redistributions of source code must retain the above copyright
7*       notice, this list of conditions and the following disclaimer.
8*     * Redistributions in binary form must reproduce the above
9*       copyright notice, this list of conditions and the following
10*       disclaimer in the documentation and/or other materials provided
11*       with the distribution.
12*     * Neither the name of The Linux Foundation nor the names of its
13*       contributors may be used to endorse or promote products derived
14*       from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*
28*/
29
30
31#define ATRACE_TAG ATRACE_TAG_CAMERA
32#define LOG_TAG "QCamera3CropRegionMapper"
33
34// Camera dependencies
35#include "QCamera3CropRegionMapper.h"
36#include "QCamera3HWI.h"
37
38extern "C" {
39#include "mm_camera_dbg.h"
40}
41
42using namespace android;
43
44namespace qcamera {
45
46/*===========================================================================
47 * FUNCTION   : QCamera3CropRegionMapper
48 *
49 * DESCRIPTION: Constructor
50 *
51 * PARAMETERS : None
52 *
53 * RETURN     : None
54 *==========================================================================*/
55QCamera3CropRegionMapper::QCamera3CropRegionMapper()
56        : mSensorW(0),
57          mSensorH(0),
58          mActiveArrayW(0),
59          mActiveArrayH(0)
60{
61}
62
63/*===========================================================================
64 * FUNCTION   : ~QCamera3CropRegionMapper
65 *
66 * DESCRIPTION: destructor
67 *
68 * PARAMETERS : none
69 *
70 * RETURN     : none
71 *==========================================================================*/
72
73QCamera3CropRegionMapper::~QCamera3CropRegionMapper()
74{
75}
76
77/*===========================================================================
78 * FUNCTION   : update
79 *
80 * DESCRIPTION: update sensor active array size and sensor output size
81 *
82 * PARAMETERS :
83 *   @active_array_w : active array width
84 *   @active_array_h : active array height
85 *   @sensor_w       : sensor output width
86 *   @sensor_h       : sensor output height
87 *
88 * RETURN     : none
89 *==========================================================================*/
90void QCamera3CropRegionMapper::update(uint32_t active_array_w,
91        uint32_t active_array_h, uint32_t sensor_w,
92        uint32_t sensor_h)
93{
94    // Sanity check
95    if (active_array_w == 0 || active_array_h == 0 ||
96            sensor_w == 0 || sensor_h == 0) {
97        LOGE("active_array size and sensor output size must be non zero");
98        return;
99    }
100    if (active_array_w < sensor_w || active_array_h < sensor_h) {
101        LOGE("invalid input: active_array [%d, %d], sensor size [%d, %d]",
102                 active_array_w, active_array_h, sensor_w, sensor_h);
103        return;
104    }
105    mSensorW = sensor_w;
106    mSensorH = sensor_h;
107    mActiveArrayW = active_array_w;
108    mActiveArrayH = active_array_h;
109
110    LOGH("active_array: %d x %d, sensor size %d x %d",
111            mActiveArrayW, mActiveArrayH, mSensorW, mSensorH);
112}
113
114/*===========================================================================
115 * FUNCTION   : toActiveArray
116 *
117 * DESCRIPTION: Map crop rectangle from sensor output space to active array space
118 *
119 * PARAMETERS :
120 *   @crop_left   : x coordinate of top left corner of rectangle
121 *   @crop_top    : y coordinate of top left corner of rectangle
122 *   @crop_width  : width of rectangle
123 *   @crop_height : height of rectangle
124 *
125 * RETURN     : none
126 *==========================================================================*/
127void QCamera3CropRegionMapper::toActiveArray(int32_t& crop_left, int32_t& crop_top,
128        int32_t& crop_width, int32_t& crop_height)
129{
130    if (mSensorW == 0 || mSensorH == 0 ||
131            mActiveArrayW == 0 || mActiveArrayH == 0) {
132        LOGE("sensor/active array sizes are not initialized!");
133        return;
134    }
135
136    crop_left = crop_left * mActiveArrayW / mSensorW;
137    crop_top = crop_top * mActiveArrayH / mSensorH;
138    crop_width = crop_width * mActiveArrayW / mSensorW;
139    crop_height = crop_height * mActiveArrayH / mSensorH;
140
141    boundToSize(crop_left, crop_top, crop_width, crop_height,
142            mActiveArrayW, mActiveArrayH);
143}
144
145/*===========================================================================
146 * FUNCTION   : toSensor
147 *
148 * DESCRIPTION: Map crop rectangle from active array space to sensor output space
149 *
150 * PARAMETERS :
151 *   @crop_left   : x coordinate of top left corner of rectangle
152 *   @crop_top    : y coordinate of top left corner of rectangle
153 *   @crop_width  : width of rectangle
154 *   @crop_height : height of rectangle
155 *
156 * RETURN     : none
157 *==========================================================================*/
158
159void QCamera3CropRegionMapper::toSensor(int32_t& crop_left, int32_t& crop_top,
160        int32_t& crop_width, int32_t& crop_height)
161{
162    if (mSensorW == 0 || mSensorH == 0 ||
163            mActiveArrayW == 0 || mActiveArrayH == 0) {
164        LOGE("sensor/active array sizes are not initialized!");
165        return;
166    }
167
168    crop_left = crop_left * mSensorW / mActiveArrayW;
169    crop_top = crop_top * mSensorH / mActiveArrayH;
170    crop_width = crop_width * mSensorW / mActiveArrayW;
171    crop_height = crop_height * mSensorH / mActiveArrayH;
172
173    LOGD("before bounding left %d, top %d, width %d, height %d",
174         crop_left, crop_top, crop_width, crop_height);
175    boundToSize(crop_left, crop_top, crop_width, crop_height,
176            mSensorW, mSensorH);
177    LOGD("after bounding left %d, top %d, width %d, height %d",
178         crop_left, crop_top, crop_width, crop_height);
179}
180
181/*===========================================================================
182 * FUNCTION   : boundToSize
183 *
184 * DESCRIPTION: Bound a particular rectangle inside a bounding box
185 *
186 * PARAMETERS :
187 *   @left    : x coordinate of top left corner of rectangle
188 *   @top     : y coordinate of top left corner of rectangle
189 *   @width   : width of rectangle
190 *   @height  : height of rectangle
191 *   @bound_w : width of bounding box
192 *   @bound_y : height of bounding box
193 *
194 * RETURN     : none
195 *==========================================================================*/
196void QCamera3CropRegionMapper::boundToSize(int32_t& left, int32_t& top,
197            int32_t& width, int32_t& height, int32_t bound_w, int32_t bound_h)
198{
199    if (left < 0) {
200        left = 0;
201    }
202    if (top < 0) {
203        top = 0;
204    }
205
206    if ((left + width) > bound_w) {
207        width = bound_w - left;
208    }
209    if ((top + height) > bound_h) {
210        height = bound_h - top;
211    }
212}
213
214/*===========================================================================
215 * FUNCTION   : toActiveArray
216 *
217 * DESCRIPTION: Map co-ordinate from sensor output space to active array space
218 *
219 * PARAMETERS :
220 *   @x   : x coordinate
221 *   @y   : y coordinate
222 *
223 * RETURN     : none
224 *==========================================================================*/
225void QCamera3CropRegionMapper::toActiveArray(uint32_t& x, uint32_t& y)
226{
227    if (mSensorW == 0 || mSensorH == 0 ||
228            mActiveArrayW == 0 || mActiveArrayH == 0) {
229        LOGE("sensor/active array sizes are not initialized!");
230        return;
231    }
232    if ((x > static_cast<uint32_t>(mSensorW)) ||
233            (y > static_cast<uint32_t>(mSensorH))) {
234        LOGE("invalid co-ordinate (%d, %d) in (0, 0, %d, %d) space",
235                 x, y, mSensorW, mSensorH);
236        return;
237    }
238    x = x * mActiveArrayW / mSensorW;
239    y = y * mActiveArrayH / mSensorH;
240}
241
242/*===========================================================================
243 * FUNCTION   : toSensor
244 *
245 * DESCRIPTION: Map co-ordinate from active array space to sensor output space
246 *
247 * PARAMETERS :
248 *   @x   : x coordinate
249 *   @y   : y coordinate
250 *
251 * RETURN     : none
252 *==========================================================================*/
253
254void QCamera3CropRegionMapper::toSensor(uint32_t& x, uint32_t& y)
255{
256    if (mSensorW == 0 || mSensorH == 0 ||
257            mActiveArrayW == 0 || mActiveArrayH == 0) {
258        LOGE("sensor/active array sizes are not initialized!");
259        return;
260    }
261
262    if ((x > static_cast<uint32_t>(mActiveArrayW)) ||
263            (y > static_cast<uint32_t>(mActiveArrayH))) {
264        LOGE("invalid co-ordinate (%d, %d) in (0, 0, %d, %d) space",
265                 x, y, mSensorW, mSensorH);
266        return;
267    }
268    x = x * mSensorW / mActiveArrayW;
269    y = y * mSensorH / mActiveArrayH;
270}
271
272}; //end namespace android
273