1use super::ImmichApiClient;
4
5#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
8pub struct OcrBox {
9 pub text: String,
10 pub x1: f64,
11 pub y1: f64,
12 pub x2: f64,
13 pub y2: f64,
14 pub x3: f64,
15 pub y3: f64,
16 pub x4: f64,
17 pub y4: f64,
18}
19
20impl OcrBox {
21 pub fn corners(&self) -> [(f64, f64); 4] {
22 [
23 (self.x1, self.y1),
24 (self.x2, self.y2),
25 (self.x3, self.y3),
26 (self.x4, self.y4),
27 ]
28 }
29}
30
31impl ImmichApiClient {
32 pub async fn fetch_asset_ocr(&self, asset_id: &str) -> Result<Vec<OcrBox>, String> {
34 let path = format!("/api/assets/{asset_id}/ocr");
35 let resp = self.send_json(reqwest::Method::GET, &path, None).await?;
36 resp.json().await.map_err(|err| err.to_string())
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn ocr_box_parses_immich_response() {
46 let json = serde_json::json!([{
47 "id": "o1",
48 "assetId": "a1",
49 "text": "EXIT",
50 "textScore": 0.98,
51 "boxScore": 0.91,
52 "x1": 0.125,
53 "y1": 0.25,
54 "x2": 0.5,
55 "y2": 0.25,
56 "x3": 0.5,
57 "y3": 0.5,
58 "x4": 0.125,
59 "y4": 0.5
60 }]);
61 let boxes: Vec<OcrBox> = serde_json::from_value(json).unwrap();
62 assert_eq!(boxes[0].text, "EXIT");
63 assert_eq!(
64 boxes[0].corners(),
65 [(0.125, 0.25), (0.5, 0.25), (0.5, 0.5), (0.125, 0.5)]
66 );
67 }
68}