|
1 | 1 | # Static Image Export |
| 2 | + |
| 3 | +The `plotly` crate provides static image export functionality through the `plotly_static` crate, which uses WebDriver and headless browsers to render plots as static images. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +Static image export allows you to convert Plotly plots into various image formats (PNG, JPEG, WEBP, SVG, PDF) for use in reports, web applications, or any scenario where you need static images. |
| 8 | + |
| 9 | +## Feature Flags |
| 10 | + |
| 11 | +The static export functionality is controlled by feature flags in the main `plotly` crate: |
| 12 | + |
| 13 | +### Required Features (choose one): |
| 14 | +- `static_export_chromedriver`: Uses Chrome/Chromium for rendering (requires chromedriver) |
| 15 | +- `static_export_geckodriver`: Uses Firefox for rendering (requires geckodriver) |
| 16 | + |
| 17 | +### Optional Features: |
| 18 | +- `static_export_downloader`: Automatically downloads WebDriver binaries at build time |
| 19 | +- `static_export_default`: Convenience feature that includes geckodriver + downloader |
| 20 | + |
| 21 | +### Cargo.toml Configuration Examples: |
| 22 | + |
| 23 | +```toml |
| 24 | +# Basic usage with manual WebDriver installation |
| 25 | +[dependencies] |
| 26 | +plotly = { version = "0.12", features = ["static_export_chromedriver"] } |
| 27 | + |
| 28 | +# With automatic WebDriver download |
| 29 | +[dependencies] |
| 30 | +plotly = { version = "0.12", features = ["static_export_chromedriver", "static_export_downloader"] } |
| 31 | + |
| 32 | +# Recommended: Default configuration with Firefox + auto-download |
| 33 | +[dependencies] |
| 34 | +plotly = { version = "0.12", features = ["static_export_default"] } |
| 35 | +``` |
| 36 | + |
| 37 | +## Prerequisites |
| 38 | + |
| 39 | +1. **WebDriver Installation**: You need either chromedriver or geckodriver installed |
| 40 | + - Chrome: Download from https://chromedriver.chromium.org/ |
| 41 | + - Firefox: Download from https://github.com/mozilla/geckodriver/releases |
| 42 | + - Or use the `static_export_downloader` feature for automatic download |
| 43 | + |
| 44 | +2. **Browser Installation**: You need Chrome/Chromium or Firefox installed |
| 45 | + |
| 46 | +3. **Environment Variable** (optional): Set `WEBDRIVER_PATH` to specify custom WebDriver location |
| 47 | + ```bash |
| 48 | + export WEBDRIVER_PATH=/path/to/chromedriver |
| 49 | + ``` |
| 50 | + |
| 51 | +## Basic Usage |
| 52 | + |
| 53 | +### Simple Export |
| 54 | + |
| 55 | +```rust |
| 56 | +use plotly::{Plot, Scatter}; |
| 57 | +use plotly::plotly_static::ImageFormat; |
| 58 | + |
| 59 | +let mut plot = Plot::new(); |
| 60 | +plot.add_trace(Scatter::new(vec![1, 2, 3], vec![4, 5, 6])); |
| 61 | + |
| 62 | +// Export to PNG file |
| 63 | +plot.write_image("my_plot", ImageFormat::PNG, 800, 600, 1.0) |
| 64 | + .expect("Failed to export plot"); |
| 65 | +``` |
| 66 | + |
| 67 | +### Efficient Exporter Reuse |
| 68 | + |
| 69 | +For better performance when exporting multiple plots, reuse a single `StaticExporter`: |
| 70 | + |
| 71 | +```rust |
| 72 | +use plotly::{Plot, Scatter}; |
| 73 | +use plotly::plotly_static::{StaticExporterBuilder, ImageFormat}; |
| 74 | + |
| 75 | +let mut plot1 = Plot::new(); |
| 76 | +plot1.add_trace(Scatter::new(vec![1, 2, 3], vec![4, 5, 6])); |
| 77 | + |
| 78 | +let mut plot2 = Plot::new(); |
| 79 | +plot2.add_trace(Scatter::new(vec![2, 3, 4], vec![5, 6, 7])); |
| 80 | + |
| 81 | +// Create a single exporter to reuse |
| 82 | +let mut exporter = StaticExporterBuilder::default() |
| 83 | + .build() |
| 84 | + .expect("Failed to create StaticExporter"); |
| 85 | + |
| 86 | +// Export multiple plots using the same exporter |
| 87 | +plot1.write_image_with_exporter(&mut exporter, "plot1", ImageFormat::PNG, 800, 600, 1.0) |
| 88 | + .expect("Failed to export plot1"); |
| 89 | +plot2.write_image_with_exporter(&mut exporter, "plot2", ImageFormat::JPEG, 800, 600, 1.0) |
| 90 | + .expect("Failed to export plot2"); |
| 91 | +``` |
| 92 | + |
| 93 | +## Supported Formats |
| 94 | + |
| 95 | +### Raster Formats |
| 96 | +- **PNG**: Portable Network Graphics, lossless compression |
| 97 | +- **JPEG**: Joint Photographic Experts Group, lossy compression (smaller files) |
| 98 | +- **WEBP**: Google's image format |
| 99 | + |
| 100 | +### Vector Formats |
| 101 | +- **SVG**: Scalable Vector Graphics |
| 102 | +- **PDF**: Portable Document Format |
| 103 | + |
| 104 | +### Deprecated |
| 105 | +- **EPS**: Encapsulated PostScript (will be removed in version 0.14.0) |
| 106 | + |
| 107 | +## String Export |
| 108 | + |
| 109 | +For web applications or APIs, you can export to strings: |
| 110 | + |
| 111 | +```rust |
| 112 | +use plotly::{Plot, Scatter}; |
| 113 | +use plotly::plotly_static::{StaticExporterBuilder, ImageFormat}; |
| 114 | + |
| 115 | +let mut plot = Plot::new(); |
| 116 | +plot.add_trace(Scatter::new(vec![1, 2, 3], vec![4, 5, 6])); |
| 117 | + |
| 118 | +let mut exporter = StaticExporterBuilder::default() |
| 119 | + .build() |
| 120 | + .expect("Failed to create StaticExporter"); |
| 121 | + |
| 122 | +// Get base64 data (useful for embedding in HTML) |
| 123 | +let base64_data = plot.to_base64_with_exporter(&mut exporter, ImageFormat::PNG, 400, 300, 1.0) |
| 124 | + .expect("Failed to export plot"); |
| 125 | + |
| 126 | +// Get SVG data (vector format, scalable) |
| 127 | +let svg_data = plot.to_svg_with_exporter(&mut exporter, 400, 300, 1.0) |
| 128 | + .expect("Failed to export plot"); |
| 129 | +``` |
| 130 | + |
| 131 | +## Advanced Configuration |
| 132 | + |
| 133 | +### Custom WebDriver Configuration |
| 134 | + |
| 135 | +```rust |
| 136 | +use plotly::plotly_static::StaticExporterBuilder; |
| 137 | + |
| 138 | +let mut exporter = StaticExporterBuilder::default() |
| 139 | + .webdriver_port(4445) // Use different port for parallel operations |
| 140 | + .spawn_webdriver(true) // Explicitly spawn WebDriver |
| 141 | + .offline_mode(true) // Use bundled JavaScript (no internet required) |
| 142 | + .webdriver_browser_caps(vec![ |
| 143 | + "--headless".to_string(), |
| 144 | + "--no-sandbox".to_string(), |
| 145 | + "--disable-gpu".to_string(), |
| 146 | + "--disable-dev-shm-usage".to_string(), |
| 147 | + ]) |
| 148 | + .build() |
| 149 | + .expect("Failed to create StaticExporter"); |
| 150 | +``` |
| 151 | + |
| 152 | +### Parallel Usage |
| 153 | + |
| 154 | +For parallel operations (tests, etc.), use unique ports: |
| 155 | + |
| 156 | +```rust |
| 157 | +use plotly::plotly_static::StaticExporterBuilder; |
| 158 | +use std::sync::atomic::{AtomicU32, Ordering}; |
| 159 | + |
| 160 | +// Generate unique ports for parallel usage |
| 161 | +static PORT_COUNTER: AtomicU32 = AtomicU32::new(4444); |
| 162 | + |
| 163 | +fn get_unique_port() -> u32 { |
| 164 | + PORT_COUNTER.fetch_add(1, Ordering::SeqCst) |
| 165 | +} |
| 166 | + |
| 167 | +// Each thread/process should use a unique port |
| 168 | +let mut exporter = StaticExporterBuilder::default() |
| 169 | + .webdriver_port(get_unique_port()) |
| 170 | + .build() |
| 171 | + .expect("Failed to build StaticExporter"); |
| 172 | +``` |
| 173 | + |
| 174 | +## Logging Support |
| 175 | + |
| 176 | +Enable logging for debugging and monitoring: |
| 177 | + |
| 178 | +```rust |
| 179 | +use plotly::plotly_static::StaticExporterBuilder; |
| 180 | + |
| 181 | +// Initialize logging (typically done once at the start of your application) |
| 182 | +env_logger::init(); |
| 183 | + |
| 184 | +// Set log level via environment variable |
| 185 | +// RUST_LOG=debug cargo run |
| 186 | + |
| 187 | +let mut exporter = StaticExporterBuilder::default() |
| 188 | + .build() |
| 189 | + .expect("Failed to create StaticExporter"); |
| 190 | +``` |
| 191 | + |
| 192 | +## Performance Considerations |
| 193 | + |
| 194 | +- **Exporter Reuse**: Create a single `StaticExporter` and reuse it for multiple plots |
| 195 | +- **Parallel Usage**: Use unique ports for parallel operations (tests, etc.) |
| 196 | +- **Resource Management**: The exporter automatically manages WebDriver lifecycle |
| 197 | +- **Format Selection**: Choose appropriate formats for your use case: |
| 198 | + - PNG: Good quality, lossless |
| 199 | + - JPEG: Smaller files, lossy |
| 200 | + - SVG: Scalable, good for web |
| 201 | + - PDF: Good for printing |
| 202 | + |
| 203 | +## Complete Example |
| 204 | + |
| 205 | +See the [static export example](../../../examples/static_export/) for a complete working example that demonstrates: |
| 206 | + |
| 207 | +- Multiple export formats |
| 208 | +- Exporter reuse |
| 209 | +- String export |
| 210 | +- Logging |
| 211 | +- Error handling |
| 212 | + |
| 213 | +To run the example: |
| 214 | + |
| 215 | +```bash |
| 216 | +cd examples/static_export |
| 217 | +cargo run |
| 218 | +``` |
| 219 | +**NOTE** Set `RUST_LOG=debug` to see detailed WebDriver operations and troubleshooting information. |
| 220 | + |
| 221 | +## Related Documentation |
| 222 | + |
| 223 | +- [plotly_static crate documentation](https://docs.rs/plotly_static/) |
| 224 | +- [WebDriver specification](https://w3c.github.io/webdriver/) |
| 225 | +- [GeckoDriver documentation](https://firefox-source-docs.mozilla.org/testing/geckodriver/) |
| 226 | +- [ChromeDriver documentation](https://chromedriver.chromium.org/) |
0 commit comments