1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
//! Contains objects representing image parameters
use crate::utils::*;

/// The region parameter defines the rectangular portion of the 
/// full image to be returned. Region can be specified by pixel coordinates, 
/// percentage or by the value “full”, which specifies that the entire image 
/// should be returned.
/// 
/// The default is Region::Full.
/// 
/// | Form | Description |
/// |-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
/// | Full | The complete image is returned, without any cropping. |
/// | Square | The region is defined as an area where the width and height are both equal to the length of the shorter dimension of the complete image. The region may be positioned anywhere in the longer dimension of the image content at the server’s discretion, and centered is often a reasonable default. |
/// | Absolute(x,y,w,h) | The region of the full image to be returned is specified in terms of absolute pixel values. The value of x represents the number of pixels from the 0 position on the horizontal axis. The value of y represents the number of pixels from the 0 position on the vertical axis. Thus the x,y position 0,0 is the upper left-most pixel of the image. w represents the width of the region and h represents the height of the region in pixels. |
/// | Percentage(x,y,w,h) | The region to be returned is specified as a sequence of percentages of the full image’s dimensions, as reported in the image information document. Thus, x represents the number of pixels from the 0 position on the horizontal axis, calculated as a percentage of the reported width. w represents the width of the region, also calculated as a percentage of the reported width. The same applies to y and h respectively. These may be floating point numbers. |#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub enum Region {
  Full,
  Square,
  Abs(Absolute),
  Pct(Percentage)
}

#[derive(Default, Debug, Clone, PartialEq)]
pub struct Absolute {
  pub x: usize,
  pub y: usize,
  pub w: usize,
  pub h: usize,
}

#[derive(Default, Debug, Clone, PartialEq)]
pub struct Percentage {
  pub x: f32,
  pub y: f32,
  pub w: f32,
  pub h: f32,
}

/// The size parameter determines the dimensions to which the extracted region is to be scaled.
/// 
/// The default is full, this setting will be deprecated in version 3.0 in favor of max
/// 
/// | Form | Description |
/// |-------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
/// | Full | The image or region is not scaled, and is returned at its full size. Note deprecation warning. |
/// | Max | The image or region is returned at the maximum size available, as indicated by maxWidth, maxHeight, maxArea in the profile description. This is the same as full if none of these properties are provided. |
/// | W(w) | The image or region should be scaled so that its width is exactly equal to w, and the height will be a calculated value that maintains the aspect ratio of the extracted region. |
/// | H(h| The image or region should be scaled so that its height is exactly equal to h, and the width will be a calculated value that maintains the aspect ratio of the extracted region. |
/// | Pct(n) | The width and height of the returned image is scaled to n% of the width and height of the extracted region. The aspect ratio of the returned image is the same as that of the extracted region. |
/// | WH(w,h) | The width and height of the returned image are exactly w and h. The aspect ratio of the returned image may be different than the extracted region, resulting in a distorted image. |
/// | LtWH(w,h) | The image content is scaled for the best fit such that the resulting width and height are less than or equal to the requested width and height. The exact scaling may be determined by the service provider, based on characteristics including image quality and system performance. The dimensions of the returned image content are calculated to maintain the aspect ratio of the extracted region. |
#[derive(Debug, Clone, PartialEq)]
pub enum Size {
  Full,
  Max,
  W(usize),
  H(usize),
  Pct(u16),
  WH(usize,usize),
  LtWH(usize, usize)
}

/// The rotation parameter specifies mirroring and rotation. A leading exclamation mark (“!”) indicates that the image should be mirrored by reflection on the vertical axis before any rotation is applied. The numerical value represents the number of degrees of clockwise rotation, and may be any floating point number from 0 to 360.
/// 
/// The default is Rotation::N(0.0)
/// 
/// | Form | Description |
/// |------|---------------------------------------------------------|
/// | Normal(n) | The degrees of clockwise rotation from 0 up to 360. |
/// | Mirror(n) | The image should be mirrored and then rotated as above. |
#[derive(Debug, Clone, PartialEq)]
pub enum Rotation {
  Normal(f32),
  Mirror(f32)
}

/// The quality parameter determines whether the image is delivered in color, grayscale or black and white.



/// 
/// The default is Quality::ServerDefault
/// 
/// | Quality | Parameter Returned |
/// |---------|-------------------------------------------------------------------------------------------------------|
/// | color | The image is returned in full color. |
/// | gray | The image is returned in grayscale, where each pixel is black, white or any shade of gray in between. |
/// | bitonal | The image returned is bitonal, where each pixel is either black or white. |
/// | default | The image is returned using the server’s default quality (e.g. color, gray or bitonal) for the image. |
#[derive(Debug, Clone, PartialEq)]
pub enum Quality {
  ServerDefault,
  Color,
  Gray,
  Bitonal
}

///The format of the returned image is expressed as an extension at the end of the URI.
/// 
/// The default is Format::Jpg
/// 
/// A format value that is unsupported should result in a 400 status code.
#[derive(Debug, Clone, PartialEq)]
pub enum Format {
  Jpg,
  Tif,
  Png,
  Gif,
  Jp2,
  Pdf,
  Webp
}

impl ToString for Region {
  fn to_string(&self) -> String {
    match self {
      Region::Full => "full".into(),
      Region::Square => "square".into(),
      Region::Abs(a) => a.to_string(),
      Region::Pct(p) => p.to_string()
    }
  }
}

impl ToString for Absolute {
  fn to_string(&self) -> String {
    join_coords(self.x, self.y, self.w, self.h)
  }
}

impl ToString for Percentage {
  fn to_string(&self) -> String {
    let floats =format_floats(vec![self.x, self.y, self.w, self.h]);
    let coords = join_coords(&floats[0], &floats[1], &floats[2], &floats[3]);
    ["pct:".to_string(), coords].join("")
  }
}

impl ToString for Size {
  fn to_string(&self) -> String {
    match self {
      Size::Full => "full".into(),
      Size::Max => "max".into(),
      Size::W(w) => format!("{},", w),
      Size::H(h) => format!(",{}", h),
      Size::Pct(n) => format!("pct:{}", n),
      Size::WH(w,h) => format!("{},{}", w, h),
      Size::LtWH(w,h) => format!("!{},{}", w, h)
    }
  }
}

impl ToString for Rotation {
  // limit float values to 3 decimal places
  fn to_string(&self) -> String {
    match self {
      Rotation::Normal(n) => format!("{:.5}", n.to_string()),
      Rotation::Mirror(n) =>  format!("!{:.5}", n.to_string())
    }
  }
}

impl ToString for Quality {
  fn to_string(&self) -> String {
    match self {
      Quality::ServerDefault => "default".into(),
      Quality::Color => "color".into(),
      Quality::Bitonal => "bitonal".into(),
      Quality::Gray => "gray".into()
    }
  }
}

impl ToString for Format {
  fn to_string(&self) -> String {
    match self {
      Format::Jpg => "jpg".into(),
      Format::Tif => "tif".into(),
      Format::Png => "png".into(),
      Format::Gif => "gif".into(),
      Format::Jp2 => "jp2".into(),
      Format::Pdf => "pdf".into(),
      Format::Webp => "webp".into()
    }
  }
}

// Default image settings
impl Default for Region {
  fn default() -> Self { Region::Full }
}

impl Default for Size {
  fn default() -> Self { Size::Full }
}

impl Default for Rotation {
  fn default() -> Self { Rotation::Normal(0.0) }
}

impl Default for Quality {
  fn default() -> Self { Quality::ServerDefault }
}

impl Default for Format {
  fn default() -> Self { Format::Jpg }
}

#[cfg(test)]
mod tests {
  use super::*;
  #[test]
  fn absolute_to_string() {
    let abs = Absolute {
      x: 1,
      y: 2,
      w: 3,
      h: 4
    };
    assert_eq!("1,2,3,4", abs.to_string());
  }
  #[test]
  fn percentage_to_string() {
    let pct = Percentage {
      x: 1.2345, 
      y: 2f32, 
      w: 3.03, 
      h: 4.0
    };
    assert_eq!("pct:1.234,2,3.03,4", pct.to_string());
  }
}