# rust-ppm
`rust-ppm` is a small RGB image and plotting library that writes binary PPM (`P6`) files.
## Image API
```rust,no_run
use rust_ppm::{Image, Pixel};
});
image.save("gradient.ppm")?;
# Ok::<(), std::io::Error>(())
```
## Plot API
`Plot` is the primary API. It automatically fits finite data, supports multiple styled series,
and renders directly to an `Image` or PPM file:
```rust,no_run
use rust_ppm::{Axes, LineStyle, MarkerStyle, Pixel, Plot};
let axes = Axes::new()
.labels("x", "x squared")
.title("Quadratic samples");
let points = [(-1.0, 1.0), (0.0, 0.0), (2.0, 4.0), (4.0, 16.0)];
Plot::new()
.size(800, 600)
.margins(80, 60)
.axes(axes)
.line(
&points,
LineStyle::new().width(3).color(Pixel::rgb(30, 100, 180)),
)
.markers(
&points,
MarkerStyle::new().size(5).color(Pixel::rgb(210, 45, 45)),
)
.save("plot.ppm")?;
# Ok::<(), std::io::Error>(())
```
`Axes::new()` automatically fits each axis to all finite series data. Override either axis with
`x_limits` or `y_limits`, and provide exact tick positions with `x_ticks` or `y_ticks`.
For larger, proportionally scaled output, add `.scale(2)` or greater. For example,
`.size(800, 600).scale(2)` writes a 1600 by 1200 image and scales margins, text, markers, and
line widths. PPM stores pixels rather than physical DPI metadata, so dimensions and scale are
the relevant quality controls.
Use `Canvas` for low-level incremental drawing or changing limits after series have been added.
Its styled methods are `line` and `markers`; the older `plot` and `scatter` methods remain
available. The `line_plot*` and `scatter_plot*` convenience functions are also retained for
compatibility.
See `src/main.rs` for examples of automatic and manual limits, custom ticks, colors, sizes,
multiple series, direct rendering, direct saving, and high-resolution output.
## Notes
- Coordinates use a bottom-left data origin; image pixels are stored from the top-left.
- Text uses a compact 8x8 bitmap font. Labels render only when the configured inset has enough room.
- PPM reading supports binary `P6` images with a maximum channel value of `255`.
## Development
```text
cargo fmt --check
cargo test --all-targets
cargo clippy --all-targets -- -D warnings
cargo doc --no-deps
```