blob: 1e96ce6e2d2f9d39705c8a79e60b95bcc6cc9082 [file] [log] [blame]
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -03001 Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver
2 =======================================================================
3
4Terminology
5-----------
6
7sensor scales: horizontal and vertical scales, configured by the sensor driver
8host scales: -"- host driver
9combined scales: sensor_scale * host_scale
10
11
12Generic scaling / cropping scheme
13---------------------------------
14
15-1--
16|
17-2-- -\
18| --\
19| --\
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -030020+-5-- . -- -3-- -\
21| `... -\
22| `... -4-- . - -7..
23| `.
24| `. .6--
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030025|
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -030026| . .6'-
27| .´
28| ... -4'- .´
29| ...´ - -7'.
30+-5'- .´ -/
31| -- -3'- -/
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030032| --/
33| --/
34-2'- -/
35|
36|
37-1'-
38
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -030039In the above chart minuses and slashes represent "real" data amounts, points and
Guennadi Liakhovetskid16290d2011-03-28 13:16:43 -030040accents represent "useful" data, basically, CEU scaled and cropped output,
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -030041mapped back onto the client's source plane.
42
43Such a configuration can be produced by user requests:
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030044
45S_CROP(left / top = (5) - (1), width / height = (5') - (5))
46S_FMT(width / height = (6') - (6))
47
48Here:
49
50(1) to (1') - whole max width or height
51(1) to (2) - sensor cropped left or top
52(2) to (2') - sensor cropped width or height
53(3) to (3') - sensor scale
54(3) to (4) - CEU cropped left or top
55(4) to (4') - CEU cropped width or height
56(5) to (5') - reverse sensor scale applied to CEU cropped width or height
57(2) to (5) - reverse sensor scale applied to CEU cropped left or top
58(6) to (6') - CEU scale - user window
59
60
61S_FMT
62-----
63
64Do not touch input rectangle - it is already optimal.
65
661. Calculate current sensor scales:
67
Guennadi Liakhovetskid16290d2011-03-28 13:16:43 -030068 scale_s = ((2') - (2)) / ((3') - (3))
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030069
702. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
71current sensor scales onto input window - this is user S_CROP:
72
73 width_u = (5') - (5) = ((4') - (4)) * scale_s
74
753. Calculate new combined scales from "effective" input window to requested user
76window:
77
78 scale_comb = width_u / ((6') - (6))
79
804. Calculate sensor output window by applying combined scales to real input
81window:
82
Guennadi Liakhovetskid16290d2011-03-28 13:16:43 -030083 width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030084
855. Apply iterative sensor S_FMT for sensor output window.
86
87 subdev->video_ops->s_fmt(.width = width_s_out)
88
896. Retrieve sensor output window (g_fmt)
90
917. Calculate new sensor scales:
92
93 scale_s_new = ((3')_new - (3)_new) / ((2') - (2))
94
958. Calculate new CEU crop - apply sensor scales to previously calculated
96"effective" crop:
97
98 width_ceu = (4')_new - (4)_new = width_u / scale_s_new
99 left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new
100
1019. Use CEU cropping to crop to the new window:
102
103 ceu_crop(.width = width_ceu, .left = left_ceu)
104
10510. Use CEU scaling to scale to the requested user window:
106
107 scale_ceu = width_ceu / width
108
109
110S_CROP
111------
112
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300113The API at http://v4l2spec.bytesex.org/spec/x1904.htm says:
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300114
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300115"...specification does not define an origin or units. However by convention
116drivers should horizontally count unscaled samples relative to 0H."
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300117
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300118We choose to follow the advise and interpret cropping units as client input
119pixels.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300120
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300121Cropping is performed in the following 6 steps:
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300122
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001231. Request exactly user rectangle from the sensor.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300124
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001252. If smaller - iterate until a larger one is obtained. Result: sensor cropped
126 to 2 : 2', target crop 5 : 5', current output format 6' - 6.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300127
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001283. In the previous step the sensor has tried to preserve its output frame as
129 good as possible, but it could have changed. Retrieve it again.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300130
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001314. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate
132 intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2)
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300133
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001345. Calculate and apply host scale = (6' - 6) / (4' - 4)
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300135
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001366. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5)
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300137
138--
139Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>