• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <cmath>
35 
36 // Camera dependencies
37 #include "QCamera3CropRegionMapper.h"
38 #include "QCamera3HWI.h"
39 
40 extern "C" {
41 #include "mm_camera_dbg.h"
42 }
43 
44 using namespace android;
45 
46 namespace qcamera {
47 
48 /*===========================================================================
49  * FUNCTION   : QCamera3CropRegionMapper
50  *
51  * DESCRIPTION: Constructor
52  *
53  * PARAMETERS : None
54  *
55  * RETURN     : None
56  *==========================================================================*/
QCamera3CropRegionMapper()57 QCamera3CropRegionMapper::QCamera3CropRegionMapper()
58         : mSensorW(0),
59           mSensorH(0),
60           mActiveArrayW(0),
61           mActiveArrayH(0)
62 {
63 }
64 
65 /*===========================================================================
66  * FUNCTION   : ~QCamera3CropRegionMapper
67  *
68  * DESCRIPTION: destructor
69  *
70  * PARAMETERS : none
71  *
72  * RETURN     : none
73  *==========================================================================*/
74 
~QCamera3CropRegionMapper()75 QCamera3CropRegionMapper::~QCamera3CropRegionMapper()
76 {
77 }
78 
79 /*===========================================================================
80  * FUNCTION   : update
81  *
82  * DESCRIPTION: update sensor active array size and sensor output size
83  *
84  * PARAMETERS :
85  *   @active_array_w : active array width
86  *   @active_array_h : active array height
87  *   @sensor_w       : sensor output width
88  *   @sensor_h       : sensor output height
89  *
90  * RETURN     : none
91  *==========================================================================*/
update(uint32_t active_array_w,uint32_t active_array_h,uint32_t sensor_w,uint32_t sensor_h)92 void QCamera3CropRegionMapper::update(uint32_t active_array_w,
93         uint32_t active_array_h, uint32_t sensor_w,
94         uint32_t sensor_h)
95 {
96     // Sanity check
97     if (active_array_w == 0 || active_array_h == 0 ||
98             sensor_w == 0 || sensor_h == 0) {
99         LOGE("active_array size and sensor output size must be non zero");
100         return;
101     }
102     if (active_array_w < sensor_w || active_array_h < sensor_h) {
103         LOGE("invalid input: active_array [%d, %d], sensor size [%d, %d]",
104                  active_array_w, active_array_h, sensor_w, sensor_h);
105         return;
106     }
107     mSensorW = sensor_w;
108     mSensorH = sensor_h;
109     mActiveArrayW = active_array_w;
110     mActiveArrayH = active_array_h;
111 
112     LOGH("active_array: %d x %d, sensor size %d x %d",
113             mActiveArrayW, mActiveArrayH, mSensorW, mSensorH);
114 }
115 
116 /*===========================================================================
117  * FUNCTION   : toActiveArray
118  *
119  * DESCRIPTION: Map crop rectangle from sensor output space to active array space
120  *
121  * PARAMETERS :
122  *   @crop_left   : x coordinate of top left corner of rectangle
123  *   @crop_top    : y coordinate of top left corner of rectangle
124  *   @crop_width  : width of rectangle
125  *   @crop_height : height of rectangle
126  *   @zoom_ratio  : zoom ratio to be reverted for the input rectangles
127  *
128  * RETURN     : none
129  *==========================================================================*/
toActiveArray(int32_t & crop_left,int32_t & crop_top,int32_t & crop_width,int32_t & crop_height,float zoom_ratio)130 void QCamera3CropRegionMapper::toActiveArray(int32_t& crop_left, int32_t& crop_top,
131         int32_t& crop_width, int32_t& crop_height, float zoom_ratio)
132 {
133     if (mSensorW == 0 || mSensorH == 0 ||
134             mActiveArrayW == 0 || mActiveArrayH == 0) {
135         LOGE("sensor/active array sizes are not initialized!");
136         return;
137     }
138     if (zoom_ratio < MIN_ZOOM_RATIO) {
139         LOGE("Invalid zoom ratio %f", zoom_ratio);
140         return;
141     }
142 
143     // Map back to activeArray space
144     float left = crop_left * mActiveArrayW / mSensorW;
145     float top = crop_top * mActiveArrayH / mSensorH;
146     float width = crop_width * mActiveArrayW / mSensorW;
147     float height = crop_height * mActiveArrayH / mSensorH;
148 
149     // Revert zoom_ratio, so that now the crop rectangle is separate from
150     // zoom_ratio. The coordinate is within the active array space which covers
151     // the post-zoom FOV.
152     left = left * zoom_ratio - (zoom_ratio - 1) * 0.5f * mActiveArrayW;
153     top = top * zoom_ratio - (zoom_ratio - 1) * 0.5f * mActiveArrayH;
154     width = width * zoom_ratio;
155     height = height * zoom_ratio;
156 
157     crop_left = std::round(left);
158     crop_top = std::round(top);
159     crop_width = std::round(width);
160     crop_height = std::round(height);
161 
162     boundToSize(crop_left, crop_top, crop_width, crop_height,
163             mActiveArrayW, mActiveArrayH);
164 }
165 
166 /*===========================================================================
167  * FUNCTION   : toSensor
168  *
169  * DESCRIPTION: Map crop rectangle from active array space to sensor output space
170  *
171  * PARAMETERS :
172  *   @crop_left   : x coordinate of top left corner of rectangle
173  *   @crop_top    : y coordinate of top left corner of rectangle
174  *   @crop_width  : width of rectangle
175  *   @crop_height : height of rectangle
176  *   @zoom_ratio  : zoom ratio to be applied to the input rectangles
177  *
178  * RETURN     : none
179  *==========================================================================*/
180 
toSensor(int32_t & crop_left,int32_t & crop_top,int32_t & crop_width,int32_t & crop_height,float zoom_ratio)181 void QCamera3CropRegionMapper::toSensor(int32_t& crop_left, int32_t& crop_top,
182         int32_t& crop_width, int32_t& crop_height, float zoom_ratio)
183 {
184     if (mSensorW == 0 || mSensorH == 0 ||
185             mActiveArrayW == 0 || mActiveArrayH == 0) {
186         LOGE("sensor/active array sizes are not initialized!");
187         return;
188     }
189 
190     applyZoomRatioHelper(crop_left, crop_top, crop_width, crop_height, zoom_ratio,
191             true /*to_sensor*/);
192 }
193 
194 /*===========================================================================
195  * FUNCTION   : applyZoomRatioHelper
196  *
197  * DESCRIPTION: Apply zoom ratio to the crop region, and optionally map
198  *              to sensor coordinate system
199  *
200  * PARAMETERS :
201  *   @crop_left   : x coordinate of top left corner of rectangle
202  *   @crop_top    : y coordinate of top left corner of rectangle
203  *   @crop_width  : width of rectangle
204  *   @crop_height : height of rectangle
205  *   @zoom_ratio  : zoom ratio to be applied to the input rectangles
206  *   @to_sensor   : whether the crop region is to be mapped to sensor coordinate
207  *                  system
208  *
209  * RETURN     : none
210  *==========================================================================*/
applyZoomRatioHelper(int32_t & crop_left,int32_t & crop_top,int32_t & crop_width,int32_t & crop_height,float zoom_ratio,bool to_sensor)211 void QCamera3CropRegionMapper::applyZoomRatioHelper(int32_t& crop_left, int32_t& crop_top,
212         int32_t& crop_width, int32_t& crop_height, float zoom_ratio, bool to_sensor)
213 {
214     if (zoom_ratio < MIN_ZOOM_RATIO) {
215         LOGE("Invalid zoom ratio %f", zoom_ratio);
216         return;
217     }
218 
219     // Apply zoom_ratio to the input rectangle in activeArray space, so that
220     // crop rectangle already takes zoom_ratio into account (in other words,
221     // coordinate within the sensor native active array space).
222     float left = crop_left / zoom_ratio +
223             0.5f * mActiveArrayW * (1.0f - 1.0f / zoom_ratio);
224     float top = crop_top / zoom_ratio +
225             0.5f * mActiveArrayH * (1.0f - 1.0f / zoom_ratio);
226     float width = crop_width / zoom_ratio;
227     float height = crop_height / zoom_ratio;
228 
229     if (to_sensor) {
230         // Map to sensor space.
231         left = left * mSensorW / mActiveArrayW;
232         top = top * mSensorH / mActiveArrayH;
233         width = width * mSensorW / mActiveArrayW;
234         height = height * mSensorH / mActiveArrayH;
235     }
236 
237     crop_left = std::round(left);
238     crop_top = std::round(top);
239     crop_width = std::round(width);
240     crop_height = std::round(height);
241 
242     LOGD("before bounding left %d, top %d, width %d, height %d",
243          crop_left, crop_top, crop_width, crop_height);
244     boundToSize(crop_left, crop_top, crop_width, crop_height,
245             to_sensor ? mSensorW : mActiveArrayW,
246             to_sensor ? mSensorH : mActiveArrayH);
247     LOGD("after bounding left %d, top %d, width %d, height %d",
248          crop_left, crop_top, crop_width, crop_height);
249 }
250 
251 /*===========================================================================
252  * FUNCTION   : applyZoomRatio
253  *
254  * DESCRIPTION: Apply zoom ratio to the crop region
255  *
256  * PARAMETERS :
257  *   @crop_left   : x coordinate of top left corner of rectangle
258  *   @crop_top    : y coordinate of top left corner of rectangle
259  *   @crop_width  : width of rectangle
260  *   @crop_height : height of rectangle
261  *   @zoom_ratio  : zoom ratio to be applied to the input rectangles
262  *
263  * RETURN     : none
264  *==========================================================================*/
applyZoomRatio(int32_t & crop_left,int32_t & crop_top,int32_t & crop_width,int32_t & crop_height,float zoom_ratio)265 void QCamera3CropRegionMapper::applyZoomRatio(int32_t& crop_left, int32_t& crop_top,
266         int32_t& crop_width, int32_t& crop_height, float zoom_ratio)
267 {
268     if (mActiveArrayW == 0 || mActiveArrayH == 0) {
269         LOGE("active array sizes are not initialized!");
270         return;
271     }
272 
273     applyZoomRatioHelper(crop_left, crop_top, crop_width, crop_height, zoom_ratio,
274         false /*to_sensor*/);
275 }
276 
277 /*===========================================================================
278  * FUNCTION   : boundToSize
279  *
280  * DESCRIPTION: Bound a particular rectangle inside a bounding box
281  *
282  * PARAMETERS :
283  *   @left    : x coordinate of top left corner of rectangle
284  *   @top     : y coordinate of top left corner of rectangle
285  *   @width   : width of rectangle
286  *   @height  : height of rectangle
287  *   @bound_w : width of bounding box
288  *   @bound_y : height of bounding box
289  *
290  * RETURN     : none
291  *==========================================================================*/
boundToSize(int32_t & left,int32_t & top,int32_t & width,int32_t & height,int32_t bound_w,int32_t bound_h)292 void QCamera3CropRegionMapper::boundToSize(int32_t& left, int32_t& top,
293             int32_t& width, int32_t& height, int32_t bound_w, int32_t bound_h)
294 {
295     if (left < 0) {
296         left = 0;
297     }
298     if (left >= bound_w) {
299         left = bound_w - 1;
300     }
301     if (top < 0) {
302         top = 0;
303     }
304     if (top >= bound_h) {
305         top = bound_h - 1;
306     }
307 
308     if ((left + width) > bound_w) {
309         width = bound_w - left;
310     }
311     if ((top + height) > bound_h) {
312         height = bound_h - top;
313     }
314 }
315 
316 /*===========================================================================
317  * FUNCTION   : toActiveArray
318  *
319  * DESCRIPTION: Map co-ordinate from sensor output space to active array space
320  *
321  * PARAMETERS :
322  *   @x   : x coordinate
323  *   @y   : y coordinate
324  *   @zoom_ratio  : zoom ratio to be applied to the input coordinates
325  *
326  * RETURN     : none
327  *==========================================================================*/
toActiveArray(uint32_t & x,uint32_t & y,float zoom_ratio)328 void QCamera3CropRegionMapper::toActiveArray(uint32_t& x, uint32_t& y, float zoom_ratio)
329 {
330     if (mSensorW == 0 || mSensorH == 0 ||
331             mActiveArrayW == 0 || mActiveArrayH == 0) {
332         LOGE("sensor/active array sizes are not initialized!");
333         return;
334     }
335     if ((x > static_cast<uint32_t>(mSensorW)) ||
336             (y > static_cast<uint32_t>(mSensorH))) {
337         LOGE("invalid co-ordinate (%d, %d) in (0, 0, %d, %d) space",
338                  x, y, mSensorW, mSensorH);
339         return;
340     }
341     if (zoom_ratio < MIN_ZOOM_RATIO) {
342         LOGE("Invalid zoom ratio %f", zoom_ratio);
343         return;
344     }
345 
346     // Map back to activeArray space
347     x = x * mActiveArrayW / mSensorW;
348     y = y * mActiveArrayH / mSensorH;
349 
350     // Revert zoom_ratio, so that now the crop rectangle is separate from
351     // zoom_ratio. The coordinate is within the active array space which covers
352     // the post-zoom FOV.
353     x = x * zoom_ratio - (zoom_ratio - 1) * 0.5f * mActiveArrayW;
354     y = y * zoom_ratio - (zoom_ratio - 1) * 0.5f * mActiveArrayH;
355 }
356 
357 /*===========================================================================
358  * FUNCTION   : toSensor
359  *
360  * DESCRIPTION: Map co-ordinate from active array space to sensor output space
361  *
362  * PARAMETERS :
363  *   @x   : x coordinate
364  *   @y   : y coordinate
365  *   @zoom_ratio  : zoom ratio to be applied to the input coordinates
366  *
367  * RETURN     : none
368  *==========================================================================*/
369 
toSensor(uint32_t & x,uint32_t & y,float zoom_ratio)370 void QCamera3CropRegionMapper::toSensor(uint32_t& x, uint32_t& y, float zoom_ratio)
371 {
372     if (mSensorW == 0 || mSensorH == 0 ||
373             mActiveArrayW == 0 || mActiveArrayH == 0) {
374         LOGE("sensor/active array sizes are not initialized!");
375         return;
376     }
377     if ((x > static_cast<uint32_t>(mActiveArrayW)) ||
378             (y > static_cast<uint32_t>(mActiveArrayH))) {
379         LOGE("invalid co-ordinate (%d, %d) in (0, 0, %d, %d) space",
380                  x, y, mSensorW, mSensorH);
381         return;
382     }
383     if (zoom_ratio < MIN_ZOOM_RATIO) {
384         LOGE("Invalid zoom ratio %f", zoom_ratio);
385         return;
386     }
387 
388     // Apply zoom_ratio to the input coordinate in activeArray space, so that
389     // coordinate already takes zoom_ratio into account (in other words,
390     // coordinate within the sensor native active array space).
391     x = x / zoom_ratio +
392             0.5f * mActiveArrayW * (1.0f - 1.0f / zoom_ratio);
393     y = y / zoom_ratio +
394             0.5f * mActiveArrayH * (1.0f - 1.0f / zoom_ratio);
395 
396     // Map to sensor space.
397     x = x * mSensorW / mActiveArrayW;
398     y = y * mSensorH / mActiveArrayH;
399 }
400 
401 }; //end namespace android
402