Commit | Line | Data |
---|---|---|
35b23b52 GL |
1 | Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver |
2 | ======================================================================= | |
3 | ||
4 | Terminology | |
5 | ----------- | |
6 | ||
7 | sensor scales: horizontal and vertical scales, configured by the sensor driver | |
8 | host scales: -"- host driver | |
9 | combined scales: sensor_scale * host_scale | |
10 | ||
11 | ||
12 | Generic scaling / cropping scheme | |
13 | --------------------------------- | |
14 | ||
15 | -1-- | |
16 | | | |
17 | -2-- -\ | |
18 | | --\ | |
19 | | --\ | |
f7fc97ad GL |
20 | +-5-- . -- -3-- -\ |
21 | | `... -\ | |
22 | | `... -4-- . - -7.. | |
23 | | `. | |
24 | | `. .6-- | |
35b23b52 | 25 | | |
f7fc97ad GL |
26 | | . .6'- |
27 | | .´ | |
28 | | ... -4'- .´ | |
29 | | ...´ - -7'. | |
30 | +-5'- .´ -/ | |
31 | | -- -3'- -/ | |
35b23b52 GL |
32 | | --/ |
33 | | --/ | |
34 | -2'- -/ | |
35 | | | |
36 | | | |
37 | -1'- | |
38 | ||
f7fc97ad | 39 | In the above chart minuses and slashes represent "real" data amounts, points and |
d16290d7 | 40 | accents represent "useful" data, basically, CEU scaled and cropped output, |
f7fc97ad GL |
41 | mapped back onto the client's source plane. |
42 | ||
43 | Such a configuration can be produced by user requests: | |
35b23b52 GL |
44 | |
45 | S_CROP(left / top = (5) - (1), width / height = (5') - (5)) | |
46 | S_FMT(width / height = (6') - (6)) | |
47 | ||
48 | Here: | |
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 | ||
61 | S_FMT | |
62 | ----- | |
63 | ||
64 | Do not touch input rectangle - it is already optimal. | |
65 | ||
66 | 1. Calculate current sensor scales: | |
67 | ||
d16290d7 | 68 | scale_s = ((2') - (2)) / ((3') - (3)) |
35b23b52 GL |
69 | |
70 | 2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at | |
71 | current sensor scales onto input window - this is user S_CROP: | |
72 | ||
73 | width_u = (5') - (5) = ((4') - (4)) * scale_s | |
74 | ||
75 | 3. Calculate new combined scales from "effective" input window to requested user | |
76 | window: | |
77 | ||
78 | scale_comb = width_u / ((6') - (6)) | |
79 | ||
80 | 4. Calculate sensor output window by applying combined scales to real input | |
81 | window: | |
82 | ||
d16290d7 | 83 | width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb |
35b23b52 GL |
84 | |
85 | 5. Apply iterative sensor S_FMT for sensor output window. | |
86 | ||
87 | subdev->video_ops->s_fmt(.width = width_s_out) | |
88 | ||
89 | 6. Retrieve sensor output window (g_fmt) | |
90 | ||
91 | 7. Calculate new sensor scales: | |
92 | ||
93 | scale_s_new = ((3')_new - (3)_new) / ((2') - (2)) | |
94 | ||
95 | 8. 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 | ||
101 | 9. Use CEU cropping to crop to the new window: | |
102 | ||
103 | ceu_crop(.width = width_ceu, .left = left_ceu) | |
104 | ||
105 | 10. Use CEU scaling to scale to the requested user window: | |
106 | ||
107 | scale_ceu = width_ceu / width | |
108 | ||
109 | ||
110 | S_CROP | |
111 | ------ | |
112 | ||
f7fc97ad | 113 | The API at http://v4l2spec.bytesex.org/spec/x1904.htm says: |
35b23b52 | 114 | |
f7fc97ad GL |
115 | "...specification does not define an origin or units. However by convention |
116 | drivers should horizontally count unscaled samples relative to 0H." | |
35b23b52 | 117 | |
f7fc97ad GL |
118 | We choose to follow the advise and interpret cropping units as client input |
119 | pixels. | |
35b23b52 | 120 | |
f7fc97ad | 121 | Cropping is performed in the following 6 steps: |
35b23b52 | 122 | |
f7fc97ad | 123 | 1. Request exactly user rectangle from the sensor. |
35b23b52 | 124 | |
f7fc97ad GL |
125 | 2. 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. | |
35b23b52 | 127 | |
f7fc97ad GL |
128 | 3. 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. | |
35b23b52 | 130 | |
f7fc97ad GL |
131 | 4. 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) | |
35b23b52 | 133 | |
f7fc97ad | 134 | 5. Calculate and apply host scale = (6' - 6) / (4' - 4) |
35b23b52 | 135 | |
f7fc97ad | 136 | 6. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5) |
35b23b52 GL |
137 | |
138 | -- | |
139 | Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> |