···1717-2-- -\1818| --\1919| --\2020-+-5-- -\ -- -3--2121-| ---\2222-| --- -4-- -\2323-| -\2424-| - -6--2020++-5-- . -- -3-- -\2121+| `... -\2222+| `... -4-- . - -7..2323+| `.2424+| `. .6--2525|2626-| - -6'-2727-| -/2828-| --- -4'- -/2929-| ---/3030-+-5'- -/3131-| -- -3'-2626+| . .6'-2727+| .´2828+| ... -4'- .´2929+| ...´ - -7'.3030++-5'- .´ -/3131+| -- -3'- -/3232| --/3333| --/3434-2'- -/···3636|3737-1'-38383939-Produced by user requests:3939+In the above chart minuses and slashes represent "real" data amounts, points and4040+accents represent "useful" data, basically, CEU scaled amd cropped output,4141+mapped back onto the client's source plane.4242+4343+Such a configuration can be produced by user requests:40444145S_CROP(left / top = (5) - (1), width / height = (5') - (5))4246S_FMT(width / height = (6') - (6))···110106S_CROP111107------112108113113-If old scale applied to new crop is invalid produce nearest new scale possible109109+The API at http://v4l2spec.bytesex.org/spec/x1904.htm says:114110115115-1. Calculate current combined scales.111111+"...specification does not define an origin or units. However by convention112112+drivers should horizontally count unscaled samples relative to 0H."116113117117- scale_comb = (((4') - (4)) / ((6') - (6))) * (((2') - (2)) / ((3') - (3)))114114+We choose to follow the advise and interpret cropping units as client input115115+pixels.118116119119-2. Apply iterative sensor S_CROP for new input window.117117+Cropping is performed in the following 6 steps:120118121121-3. If old combined scales applied to new crop produce an impossible user window,122122-adjust scales to produce nearest possible window.119119+1. Request exactly user rectangle from the sensor.123120124124- width_u_out = ((5') - (5)) / scale_comb121121+2. If smaller - iterate until a larger one is obtained. Result: sensor cropped122122+ to 2 : 2', target crop 5 : 5', current output format 6' - 6.125123126126- if (width_u_out > max)127127- scale_comb = ((5') - (5)) / max;128128- else if (width_u_out < min)129129- scale_comb = ((5') - (5)) / min;124124+3. In the previous step the sensor has tried to preserve its output frame as125125+ good as possible, but it could have changed. Retrieve it again.130126131131-4. Issue G_CROP to retrieve actual input window.127127+4. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate128128+ intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2)132129133133-5. Using actual input window and calculated combined scales calculate sensor134134-target output window.130130+5. Calculate and apply host scale = (6' - 6) / (4' - 4)135131136136- width_s_out = ((3') - (3)) = ((2') - (2)) / scale_comb137137-138138-6. Apply iterative S_FMT for new sensor target output window.139139-140140-7. Issue G_FMT to retrieve the actual sensor output window.141141-142142-8. Calculate sensor scales.143143-144144- scale_s = ((3') - (3)) / ((2') - (2))145145-146146-9. Calculate sensor output subwindow to be cropped on CEU by applying sensor147147-scales to the requested window.148148-149149- width_ceu = ((5') - (5)) / scale_s150150-151151-10. Use CEU cropping for above calculated window.152152-153153-11. Calculate CEU scales from sensor scales from results of (10) and user window154154-from (3)155155-156156- scale_ceu = calc_scale(((5') - (5)), &width_u_out)157157-158158-12. Apply CEU scales.132132+6. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5)159133160134--161135Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>