openai_req/image/
mod.rs

1use crate::{ FormRequest, JsonRequest};
2
3use std::io::Error;
4use std::io::ErrorKind::NotFound;
5use std::path::PathBuf;
6use serde::{Deserialize, Serialize};
7use reqwest::multipart::Part;
8use async_trait::async_trait;
9use tokio::try_join;
10use crate::conversions::AsyncTryFrom;
11use crate::file_to_part;
12
13///Generates image from text prompt.
14///Details at https://platform.openai.com/docs/api-reference/images/create
15/// # Usage example
16///```
17/// use openai_req::image::ImageRequest;
18/// use openai_req::JsonRequest;
19///
20/// let prompt = "cool company logo".to_string();
21/// let req = ImageRequest::new(prompt);
22/// let res = req.run(&client).await?;
23/// ```
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ImageRequest {
26    prompt: String,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    n: Option<u32>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    size: Option<ImageSize>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    response_format: Option<String>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    user: Option<String>,
35}
36
37impl JsonRequest<ImageResponse> for ImageRequest{
38    const ENDPOINT: &'static str = "/images/generations";
39}
40
41impl ImageRequest {
42    pub fn new(prompt: String) -> Self {
43        Self {
44            prompt,
45            n: None,
46            size: None,
47            response_format: None,
48            user: None,
49        }
50    }
51
52    pub fn n(mut self, n: u32) -> Self {
53        self.n = Some(n);
54        self
55    }
56
57    pub fn size(mut self, size: ImageSize) -> Self {
58        self.size = Some(size);
59        self
60    }
61
62    pub fn response_format(mut self, response_format: String) -> Self {
63        self.response_format = Some(response_format);
64        self
65    }
66
67    pub fn user(mut self, user: String) -> Self {
68        self.user = Some(user);
69        self
70    }
71}
72
73///Generates image edit for provided image.
74///Details at https://platform.openai.com/docs/api-reference/images/create-edit
75/// # Usage example
76///```
77/// use openai_req::image::ImageEditRequest;
78/// use std::path::PathBuf;
79/// use openai_req::FormRequest;
80///
81/// let image_path = PathBuf::from("tests/generated.png");
82/// let mask_path = PathBuf::from("tests/mask.png");
83/// let prompt = "remove text".to_string();
84/// let req = ImageEditRequest::new(image_path,prompt)?
85///         .mask(mask_path)?;
86/// let res = req.run(&client).await?;
87/// ```
88#[derive(Debug,Clone)]
89pub struct ImageEditRequest {
90    image: PathBuf,
91    mask: Option<PathBuf>,
92    prompt: String,
93    n: Option<i32>,
94    size: Option<ImageSize>,
95    response_format: Option<String>,
96    user: Option<String>
97}
98
99impl FormRequest<ImageResponse> for ImageEditRequest{
100    const ENDPOINT: &'static str = "/images/edits";
101}
102
103impl ImageEditRequest{
104
105    /// Will check if provided path exists, and return io::Error if it does not.
106    pub fn new(image:PathBuf, prompt: String) -> Result<Self,Error> {
107        if image.exists() {
108            return Ok(
109                Self {
110                    image,
111                    mask: None,
112                    prompt,
113                    n: None,
114                    size: None,
115                    response_format: None,
116                    user: None,
117                })
118        }
119        Err(Error::new(NotFound, "File does not exist"))
120    }
121
122    /// Will check if provided path exists, and return io::Error if it does not.
123    pub fn mask(mut self, mask: PathBuf) ->  Result<Self,Error> {
124        if mask.exists() {
125            self.mask = Some(mask);
126            return Ok(self)
127        }
128        Err(Error::new(NotFound, "File does not exist"))
129    }
130
131    pub fn n(mut self, n: i32) -> Self {
132        self.n = Some(n);
133        self
134    }
135
136    pub fn size(mut self, size: ImageSize) -> Self {
137        self.size = Some(size);
138        self
139    }
140
141    pub fn response_format(mut self, response_format: String) -> Self {
142        self.response_format = Some(response_format);
143        self
144    }
145
146    pub fn user(mut self, user: String) -> Self {
147        self.user = Some(user);
148        self
149    }
150
151}
152
153#[async_trait]
154impl AsyncTryFrom<ImageEditRequest> for reqwest::multipart::Form {
155
156    type Error = Error;
157
158    async fn try_from(request: ImageEditRequest) -> Result<Self, Self::Error> {
159        let mut form = reqwest::multipart::Form::new()
160            .part("prompt", Part::text(request.prompt));
161
162        if let Some(mask) = request.mask {
163            let (mask,image)= try_join!(file_to_part(&mask),file_to_part(&request.image))?;
164            form =
165                form.part("image", image)
166                    .part("mask", mask);
167        }else {
168            form = form.part("image", file_to_part(&request.image).await?)
169        }
170        if let Some(n) = request.n {
171            form = form.part("n", Part::text(n.to_string()));
172        }
173        if let Some(size) = request.size {
174            form = form.part("size", Part::text(size.to_string()));
175        }
176        if let Some(response_format) = request.response_format {
177            form = form.part("response_format", Part::text(response_format));
178        }
179        if let Some(user) = request.user {
180            form = form.part("user", Part::text(user));
181        }
182        return Ok(form)
183    }
184}
185
186///Generates variation for provided image.
187///Details at https://platform.openai.com/docs/api-reference/images/create-variation
188/// # Usage example
189///```
190/// use std::path::PathBuf;
191/// use openai_req::FormRequest;
192/// use openai_req::image::ImageVariationRequest;
193///
194/// let image_path = PathBuf::from("tests/generated.png");
195/// let req = ImageVariationRequest::new(image_path)?;
196/// let res = req.run(&client).await?;
197/// ```
198#[derive(Debug,Clone)]
199pub struct ImageVariationRequest {
200    image: PathBuf,
201    n: Option<u32>,
202    size: Option<ImageSize>,
203    user: Option<String>
204}
205
206impl FormRequest<ImageResponse> for ImageVariationRequest{
207    const ENDPOINT: &'static str = "/images/variations";
208}
209
210impl ImageVariationRequest {
211    pub fn new(image: PathBuf) -> Result<Self,Error> {
212        if image.exists() {
213            return Ok(
214                Self {
215                    image,
216                    n: None,
217                    size: None,
218                    user: None,
219                }
220            )
221        }
222        Err(Error::new(NotFound, "File does not exist"))
223    }
224
225    pub fn n(mut self, n: u32) -> Self {
226        self.n = Some(n);
227        self
228    }
229
230    pub fn size(mut self, size: ImageSize) -> Self {
231        self.size = Some(size);
232        self
233    }
234
235    pub fn user(mut self, user: String) -> Self {
236        self.user = Some(user);
237        self
238    }
239}
240
241#[async_trait]
242impl AsyncTryFrom<ImageVariationRequest> for reqwest::multipart::Form {
243
244    type Error = Error;
245
246    async fn try_from(request: ImageVariationRequest) -> Result<Self, Self::Error> {
247        let mut form = reqwest::multipart::Form::new()
248            .part("image", file_to_part(&request.image).await?);
249        if let Some(n) = request.n {
250            form = form.part("n", Part::text(n.to_string()));
251        }
252        if let Some(size) = request.size {
253            form = form.part("size", Part::text(size.to_string()));
254        }
255        if let Some(user) = request.user {
256            form = form.part("user", Part::text(user));
257        }
258        return Ok(form)
259    }
260}
261
262
263#[derive(Debug,Clone,Serialize,Deserialize)]
264pub struct ImageResponse {
265    pub created: i64,
266    pub data: Vec<ImageData>,
267}
268
269#[derive(Debug,Clone,Serialize, Deserialize)]
270pub struct ImageData {
271    pub url: String,
272}
273
274#[derive(Debug,Clone, Serialize, Deserialize)]
275pub enum ImageSize {
276    #[serde(rename = "256x256")]
277    S256,
278    #[serde(rename = "512x512")]
279    S512,
280    #[serde(rename = "1024x1024")]
281    S1024,
282}
283
284impl ToString for ImageSize {
285    fn to_string(&self) -> String {
286        match *self {
287            ImageSize::S256 => String::from("256x256"),
288            ImageSize::S512 => String::from("512x512"),
289            ImageSize::S1024 => String::from("1024x1024"),
290        }
291    }
292}
293
294impl ImageSize {
295    pub fn from_string(s: &str) -> Option<Self> {
296        match s {
297            "256x256" => Some(ImageSize::S256),
298            "512x512" => Some(ImageSize::S512),
299            "1024x1024" => Some(ImageSize::S1024),
300            _ => None,
301        }
302    }
303}
304
305