@@ -12,7 +12,14 @@ Decode the JPEG image as colorant matrix. The source data can be either a filena
12
12
before encoding. The default value is `false`.
13
13
- `scale_ratio::Real`: scale the image by ratio `scale_ratio` in `M/8` with `M ∈ 1:16`. The
14
14
default value is `1`. For values are not in the range, they will be mapped to the nearest
15
- value, e.g., `0.3 => 2/8` and `0.35 => 3/8`.
15
+ value, e.g., `0.3 => 2/8` and `0.35 => 3/8`. `scale_ratio` and `preferred_size` may not be
16
+ used together.
17
+ - `preferred_size::Tuple`: infer the minimal `scale_ratio` that `all(size(out) .>=
18
+ preferred_size))` holds. It can optionally be `(op, preferred_size)` format, with compare
19
+ operation `op` be one of `>`, `>=`, `<` or `<=`. If `op in (>=, >)` then it gets the
20
+ minimal `scale_ratio`, otherwise it gets the maximum `scale_ratio` for `op in (<=, <)`.
21
+ `scale_ratio` and `preferred_size` may not be used together. The `preferred_size`
22
+ dimensions are not affected by keyword `transpose`.
16
23
17
24
# Examples
18
25
@@ -52,7 +59,8 @@ function jpeg_decode(
52
59
:: Type{CT} ,
53
60
data:: Vector{UInt8} ;
54
61
transpose= false ,
55
- scale_ratio= 1 ) where CT<: Colorant
62
+ scale_ratio:: Union{Nothing,Real} = nothing ,
63
+ preferred_size:: Union{Nothing,Tuple} = nothing ) where CT<: Colorant
56
64
_jpeg_check_bytes (data)
57
65
out_CT, jpeg_cls = _jpeg_out_color_space (CT)
58
66
@@ -66,7 +74,14 @@ function jpeg_decode(
66
74
LibJpeg. jpeg_read_header (cinfo_ref, true )
67
75
68
76
# set decompression parameters, if given
69
- r = _cal_scale_ratio (scale_ratio)
77
+ if ! isnothing (preferred_size) && ! transpose
78
+ if preferred_size[1 ] isa Function
79
+ preferred_size = (preferred_size[1 ], reverse (preferred_size[2 ]))
80
+ else
81
+ preferred_size = reverse (preferred_size)
82
+ end
83
+ end
84
+ r = _cal_scale_ratio (scale_ratio, preferred_size, cinfo)
70
85
cinfo. scale_num, cinfo. scale_denom = r. num, r. den
71
86
cinfo. out_color_space = jpeg_cls
72
87
@@ -127,7 +142,37 @@ _jpeg_decode!(out::Matrix{<:Colorant}, cinfo::LibJpeg.jpeg_decompress_struct) =
127
142
128
143
# libjpeg-turbo only supports ratio M/8 with M from 1 to 16
129
144
const _allowed_scale_ratios = ntuple (i-> i// 8 , 16 )
130
- _cal_scale_ratio (r:: Real ) = _allowed_scale_ratios[findmin (x-> abs (x- r), _allowed_scale_ratios)[2 ]]
145
+ function _cal_scale_ratio (:: Real , :: Tuple , cinfo)
146
+ throw (ArgumentError (" Keywords `aspect_ratio` and `preferred_size` are exclusive to each other: you should only specify one of them." ))
147
+ end
148
+ _cal_scale_ratio (:: Nothing , :: Nothing , cinfo) = 1 // 1
149
+ _cal_scale_ratio (r:: Real , :: Nothing , cinfo) = _allowed_scale_ratios[findmin (x-> abs (x- r), _allowed_scale_ratios)[2 ]]
150
+ function _cal_scale_ratio (:: Nothing , preferred_size:: Tuple , cinfo)
151
+ cinfo. scale_num, cinfo. scale_denom = 1 , 1
152
+ LibJpeg. jpeg_calc_output_dimensions (Ref (cinfo))
153
+ out_size = (Int (cinfo. output_width), Int (cinfo. output_height))
154
+ op, preferred_size = if preferred_size[1 ] isa Function
155
+ op = preferred_size[1 ]
156
+ op in (> , >= , < , <= ) || throw (ArgumentError (" the compare operation must be one of `>`, `>=`, `<` and `<=`." ))
157
+ op, preferred_size[2 ]
158
+ else
159
+ >= , preferred_size
160
+ end
161
+ if op in (> , >= )
162
+ idx = findfirst (x-> all (op .(x .* out_size, preferred_size)), _allowed_scale_ratios)
163
+ if isnothing (idx)
164
+ @warn " Failed to infer appropriate scale ratio, use `scale_ratio=2` instead." actual_size= out_size preferred_size
165
+ idx = length (_allowed_scale_ratios)
166
+ end
167
+ elseif op in (< , <= )
168
+ idx = findlast (x-> all (op .(x .* out_size, preferred_size)), _allowed_scale_ratios)
169
+ if isnothing (idx)
170
+ @warn " Failed to infer appropriate scale ratio, use `scale_ratio=1/8` instead." actual_size= out_size preferred_size
171
+ idx = 1
172
+ end
173
+ end
174
+ return _allowed_scale_ratios[idx]
175
+ end
131
176
132
177
function _default_out_color_space (filename:: AbstractString )
133
178
_jpeg_check_bytes (filename)
0 commit comments