plotly/
export.rs

1#[cfg(feature = "plotly_static")]
2pub mod sync {
3    use std::path::Path;
4
5    use crate::{plot::Plot, ImageFormat};
6
7    /// Extension methods for exporting plots using a synchronous exporter.
8    pub trait ExporterSyncExt {
9        /// Convert the `Plot` to a static image of the given image format and
10        /// save at the given location using a provided StaticExporter.
11        ///
12        /// This method allows you to reuse a StaticExporter instance across
13        /// multiple plots, which is more efficient than creating a new one for
14        /// each operation.
15        ///
16        /// This method requires the usage of the `plotly_static` crate using
17        /// one of the available feature flags. For advanced usage (parallelism, exporter reuse, custom config), see the [plotly_static documentation](https://docs.rs/plotly_static/).
18        ///
19        /// # Arguments
20        ///
21        /// * `exporter` - A mutable reference to a StaticExporter instance
22        /// * `filename` - The destination path for the output file
23        /// * `format` - The desired output image format
24        /// * `width` - The width of the output image in pixels
25        /// * `height` - The height of the output image in pixels
26        /// * `scale` - The scale factor for the image (1.0 = normal size)
27        ///
28        /// # Examples
29        ///
30        /// ```no_run
31        /// use plotly::{Plot, Scatter};
32        /// use plotly::export::sync::ExporterSyncExt as _;
33        /// use plotly::plotly_static::{StaticExporterBuilder, ImageFormat};
34        ///
35        /// let mut plot = Plot::new();
36        /// plot.add_trace(Scatter::new(vec![1, 2, 3], vec![4, 5, 6]));
37        ///
38        /// let mut exporter = StaticExporterBuilder::default()
39        ///     .build()
40        ///     .expect("Failed to create StaticExporter");
41        ///
42        /// // Export multiple plots using the same exporter
43        /// exporter.write_image(&plot, "plot1", ImageFormat::PNG, 800, 600, 1.0)
44        ///     .expect("Failed to export plot");
45        ///
46        /// exporter.close();
47        /// ```
48        fn write_image<P: AsRef<Path>>(
49            &mut self,
50            plot: &Plot,
51            filename: P,
52            format: ImageFormat,
53            width: usize,
54            height: usize,
55            scale: f64,
56        ) -> Result<(), Box<dyn std::error::Error>>;
57
58        /// Convert the `Plot` to a static image and return the image as a
59        /// `base64` string. Supported formats are [ImageFormat::JPEG],
60        /// [ImageFormat::PNG] and [ImageFormat::WEBP].
61        ///
62        /// This method allows you to reuse the same StaticExporter instance
63        /// across multiple plots, which is more efficient than creating
64        /// a new one for each operation.
65        ///
66        /// For advanced usage (parallelism, exporter reuse, custom config), see the [plotly_static documentation](https://docs.rs/plotly_static/).
67        ///
68        /// # Arguments
69        ///
70        /// * `format` - The desired output image format
71        /// * `width` - The width of the output image in pixels
72        /// * `height` - The height of the output image in pixels
73        /// * `scale` - The scale factor for the image (1.0 = normal size)
74        ///
75        /// # Examples
76        ///
77        /// ```no_run
78        /// use plotly::{Plot, Scatter};
79        /// use plotly::export::sync::ExporterSyncExt as _;
80        /// use plotly::plotly_static::{StaticExporterBuilder, ImageFormat};
81        ///
82        /// let mut plot = Plot::new();
83        /// plot.add_trace(Scatter::new(vec![1, 2, 3], vec![4, 5, 6]));
84        ///
85        /// let mut exporter = StaticExporterBuilder::default()
86        ///     .build()
87        ///     .expect("Failed to create StaticExporter");
88        ///
89        /// let base64_data = exporter.to_base64(&plot, ImageFormat::PNG, 800, 600, 1.0)
90        ///     .expect("Failed to export plot");
91        ///
92        /// exporter.close();
93        /// ```
94        fn to_base64(
95            &mut self,
96            plot: &Plot,
97            format: ImageFormat,
98            width: usize,
99            height: usize,
100            scale: f64,
101        ) -> Result<String, Box<dyn std::error::Error>>;
102
103        /// Convert the `Plot` to SVG and return it as a String.
104        ///
105        /// This method allows you to reuse the same StaticExporter instance
106        /// across multiple plots, which is more efficient than creating
107        /// a new one for each operation.
108        ///
109        /// For advanced usage (parallelism, exporter reuse, custom config), see the [plotly_static documentation](https://docs.rs/plotly_static/).
110        ///
111        /// # Arguments
112        ///
113        /// * `width` - The width of the output image in pixels
114        /// * `height` - The height of the output image in pixels
115        /// * `scale` - The scale factor for the image (1.0 = normal size)
116        ///
117        /// # Examples
118        ///
119        /// ```no_run
120        /// use plotly::{Plot, Scatter};
121        /// use plotly::export::sync::ExporterSyncExt as _;
122        /// use plotly::plotly_static::{StaticExporterBuilder, ImageFormat};
123        ///
124        /// let mut plot = Plot::new();
125        /// plot.add_trace(Scatter::new(vec![1, 2, 3], vec![4, 5, 6]));
126        ///
127        /// let mut exporter = StaticExporterBuilder::default()
128        ///     .build()
129        ///     .expect("Failed to create StaticExporter");
130        ///
131        /// let svg_data = exporter.to_svg(&plot, 800, 600, 1.0)
132        ///     .expect("Failed to export plot");
133        ///
134        /// exporter.close();
135        /// ```
136        fn to_svg(
137            &mut self,
138            plot: &Plot,
139            width: usize,
140            height: usize,
141            scale: f64,
142        ) -> Result<String, Box<dyn std::error::Error>>;
143    }
144
145    impl ExporterSyncExt for plotly_static::StaticExporter {
146        fn write_image<P: AsRef<Path>>(
147            &mut self,
148            plot: &Plot,
149            filename: P,
150            format: ImageFormat,
151            width: usize,
152            height: usize,
153            scale: f64,
154        ) -> Result<(), Box<dyn std::error::Error>> {
155            self.write_fig(
156                filename.as_ref(),
157                &serde_json::to_value(plot)?,
158                format,
159                width,
160                height,
161                scale,
162            )
163        }
164
165        fn to_base64(
166            &mut self,
167            plot: &Plot,
168            format: ImageFormat,
169            width: usize,
170            height: usize,
171            scale: f64,
172        ) -> Result<String, Box<dyn std::error::Error>> {
173            match format {
174                ImageFormat::JPEG | ImageFormat::PNG | ImageFormat::WEBP => self.write_to_string(
175                    &serde_json::to_value(plot)?,
176                    format,
177                    width,
178                    height,
179                    scale,
180                ),
181                _ => Err(format!(
182                    "Cannot generate base64 string for ImageFormat:{format}. Allowed formats are JPEG, PNG, WEBP"
183                )
184                .into()),
185            }
186        }
187
188        fn to_svg(
189            &mut self,
190            plot: &Plot,
191            width: usize,
192            height: usize,
193            scale: f64,
194        ) -> Result<String, Box<dyn std::error::Error>> {
195            self.write_to_string(
196                &serde_json::to_value(plot)?,
197                ImageFormat::SVG,
198                width,
199                height,
200                scale,
201            )
202        }
203    }
204}
205
206#[cfg(feature = "plotly_static")]
207pub mod r#async {
208    use std::path::Path;
209
210    use async_trait::async_trait;
211
212    use crate::{plot::Plot, ImageFormat};
213
214    /// Extension methods for exporting plots using an asynchronous exporter.
215    #[async_trait(?Send)]
216    pub trait ExporterAsyncExt {
217        /// Convert the `Plot` to a static image of the given format and save at
218        /// the given location using the asynchronous exporter.
219        ///
220        /// The exporter must have been built with the `build_async` method of
221        /// the StaticExporterBuilder.
222        ///
223        /// Functionally signature equivalent to the sync version in
224        /// [`crate::export::sync::ExporterSyncExt::write_image`], but meant for
225        /// async contexts.
226        ///
227        /// For more details see the [plotly_static documentation](https://docs.rs/plotly_static/).
228        async fn write_image<P: AsRef<Path>>(
229            &mut self,
230            plot: &Plot,
231            filename: P,
232            format: ImageFormat,
233            width: usize,
234            height: usize,
235            scale: f64,
236        ) -> Result<(), Box<dyn std::error::Error>>;
237
238        /// Convert the `Plot` to a static image and return the image as a
239        /// `base64` string using the asynchronous exporter.
240        ///
241        /// The exporter must have been built with the `build_async` method of
242        /// the StaticExporterBuilder.
243        ///
244        /// Functionally signature equivalent to the sync version in
245        /// [`crate::export::sync::ExporterSyncExt::to_base64`], but meant for
246        /// async contexts.
247        ///
248        /// For more details see the [plotly_static documentation](https://docs.rs/plotly_static/).
249        async fn to_base64(
250            &mut self,
251            plot: &Plot,
252            format: ImageFormat,
253            width: usize,
254            height: usize,
255            scale: f64,
256        ) -> Result<String, Box<dyn std::error::Error>>;
257
258        /// Convert the `Plot` to SVG and return it as a String using the
259        /// asynchronous exporter.
260        ///
261        /// Functionally signature equivalent to the sync version in
262        /// [`crate::export::sync::ExporterSyncExt::to_svg`], but meant for
263        /// async contexts.
264        ///
265        /// For more details see the [plotly_static documentation](https://docs.rs/plotly_static/).
266        async fn to_svg(
267            &mut self,
268            plot: &Plot,
269            width: usize,
270            height: usize,
271            scale: f64,
272        ) -> Result<String, Box<dyn std::error::Error>>;
273    }
274
275    #[async_trait(?Send)]
276    impl ExporterAsyncExt for plotly_static::AsyncStaticExporter {
277        async fn write_image<P: AsRef<Path>>(
278            &mut self,
279            plot: &Plot,
280            filename: P,
281            format: ImageFormat,
282            width: usize,
283            height: usize,
284            scale: f64,
285        ) -> Result<(), Box<dyn std::error::Error>> {
286            self.write_fig(
287                filename.as_ref(),
288                &serde_json::to_value(plot)?,
289                format,
290                width,
291                height,
292                scale,
293            )
294            .await
295        }
296
297        async fn to_base64(
298            &mut self,
299            plot: &Plot,
300            format: ImageFormat,
301            width: usize,
302            height: usize,
303            scale: f64,
304        ) -> Result<String, Box<dyn std::error::Error>> {
305            match format {
306                ImageFormat::JPEG | ImageFormat::PNG | ImageFormat::WEBP => self
307                    .write_to_string(
308                        &serde_json::to_value(plot)?,
309                        format,
310                        width,
311                        height,
312                        scale,
313                    )
314                    .await,
315                _ => Err(format!(
316                    "Cannot generate base64 string for ImageFormat:{format}. Allowed formats are JPEG, PNG, WEBP"
317                )
318                .into()),
319            }
320        }
321
322        async fn to_svg(
323            &mut self,
324            plot: &Plot,
325            width: usize,
326            height: usize,
327            scale: f64,
328        ) -> Result<String, Box<dyn std::error::Error>> {
329            self.write_to_string(
330                &serde_json::to_value(plot)?,
331                ImageFormat::SVG,
332                width,
333                height,
334                scale,
335            )
336            .await
337        }
338    }
339}