pdf2image_alt/
render_options.rs1#[derive(derive_builder::Builder)]
3pub struct RenderOptions {
4 #[builder(default = "DPI::Uniform(150)")]
5 pub resolution: DPI,
7 #[builder(setter(into, strip_option), default)]
8 pub scale: Option<Scale>,
10 #[builder(default)]
11 pub greyscale: bool,
13 #[builder(setter(into, strip_option), default)]
14 pub crop: Option<Crop>,
16 #[builder(setter(into, strip_option), default)]
17 pub password: Option<Password>,
19 #[builder(default)]
21 pub pdftocairo: bool,
22}
23
24impl Default for RenderOptions {
25 fn default() -> Self {
26 Self {
27 resolution: DPI::Uniform(150),
28 scale: None,
29 greyscale: false,
30 crop: None,
31 password: None,
32 pdftocairo: false,
33 }
34 }
35}
36
37impl RenderOptions {
38 pub fn to_cli_args(&self) -> Vec<String> {
39 let mut args = vec![];
40
41 match self.resolution {
42 DPI::Uniform(dpi) => {
43 args.push("-r".to_string());
44 args.push(dpi.to_string());
45 }
46 DPI::XY(dpi_x, dpi_y) => {
47 args.push("-rx".to_string());
48 args.push(dpi_x.to_string());
49 args.push("-ry".to_string());
50 args.push(dpi_y.to_string());
51 }
52 }
53
54 if let Some(scale) = &self.scale {
55 match scale {
56 Scale::Uniform(scale) => {
57 args.push("-scale-to".to_string());
58 args.push(scale.to_string());
59 }
60 Scale::X(scale_x) => {
61 args.push("-scale-to-x".to_string());
62 args.push(scale_x.to_string());
63 }
64 Scale::Y(scale_y) => {
65 args.push("-scale-to-y".to_string());
66 args.push(scale_y.to_string());
67 }
68 Scale::XY(scale_x, scale_y) => {
69 args.push("-scale-to-x".to_string());
70 args.push(scale_x.to_string());
71 args.push("-scale-to-y".to_string());
72 args.push(scale_y.to_string());
73 }
74 }
75 }
76
77 if self.greyscale {
78 args.push("-gray".to_string());
79 }
80
81 if let Some(crop) = &self.crop {
82 args.push("-cropbox".to_string());
83 let (x, y) = (crop.inner.x, crop.inner.y);
84 let (width, height) = (crop.inner.width, crop.inner.height);
85 args.push("-x".to_string());
86 args.push(x.to_string());
87 args.push("-y".to_string());
88 args.push(y.to_string());
89 args.push("-W".to_string());
90 args.push(width.to_string());
91 args.push("-H".to_string());
92 args.push(height.to_string());
93 }
94
95 if let Some(password) = &self.password {
96 match password {
97 Password::User(password) => {
98 args.push("-upw".to_string());
99 args.push(password.clone());
100 }
101 Password::Owner(password) => {
102 args.push("-opw".to_string());
103 args.push(password.clone());
104 }
105 }
106 }
107
108 args
109 }
110}
111
112#[derive(Debug, Clone)]
114pub enum Password {
115 User(String),
116 Owner(String),
117}
118
119#[derive(Debug, Clone)]
121pub enum DPI {
122 Uniform(u32),
124 XY(u32, u32),
126}
127
128#[derive(Debug, Clone)]
130pub enum Scale {
131 Uniform(u32),
133 X(u32),
135 Y(u32),
137 XY(u32, u32),
139}
140
141#[derive(Debug, Clone)]
143pub struct Crop {
144 inner: image::math::Rect,
145}
146
147impl Crop {
148 pub fn new(x1: u32, y1: u32, x2: u32, y2: u32) -> Self {
149 let (min_x, max_x) = match x1 < x2 {
150 true => (x1, x2),
151 false => (x2, x1),
152 };
153
154 let (min_y, max_y) = match y1 < y2 {
155 true => (y1, y2),
156 false => (y2, y1),
157 };
158
159 Self {
160 inner: image::math::Rect {
161 x: min_x,
162 y: min_y,
163 width: max_x - min_x,
164 height: max_y - min_y,
165 },
166 }
167 }
168
169 pub fn from_top_left(width: u32, height: u32, top_left: (u32, u32)) -> Self {
170 Self {
171 inner: image::math::Rect {
172 x: top_left.0,
173 y: top_left.1,
174 width,
175 height,
176 },
177 }
178 }
179
180 pub fn square(size: u32, top_left: (u32, u32)) -> Self {
181 Self {
182 inner: image::math::Rect {
183 x: top_left.0,
184 y: top_left.1,
185 width: size,
186 height: size,
187 },
188 }
189 }
190}