plotters icon indicating copy to clipboard operation
plotters copied to clipboard

[BUG] GIF backend sometimes produces incorrect color in the image

Open apirogov opened this issue 10 months ago • 0 comments

Describe the bug

I tried everything I could, at this point I guess its some low-level backend implementation error. Sometimes, in certain constellations of plotting setups (certain polygons, certain chart bounds, etc.), I get the wrong color for the vertex circles.

With animated GIFs, the bug appears per-frame (some different polygon on a following frame still can be rendered correctly).

I have more than two sequences where I have this issue popping up, I just picked out two.

I would appreciate any help, right now this is frustrating me so much that I consider looking for a different plotting library, even though except for that I think that plotters is amazing :(

Okay:

Image

Buggy:

Image

Also buggy:

Image

To Reproduce

use plotters::prelude::*;

fn main() {
    let okay: &[(f64, f64)] = &[(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)];

    let bug1: &[(f64, f64)] = &[
        (0.0, 0.0),
        (-0.5, -0.8660254037844386),
        (0.3660254037844386, -0.3660254037844386),
        (-0.1339745962155614, 0.5),
        (-1.0, 0.0),
        (0.0, 0.0),
    ];
    let bug2: &[(f64, f64)] = &[
        (0.0, 0.0),
        (0.8660254037844386, -0.5),
        (0.3660254037844386, 0.3660254037844386),
        (-0.5, 0.8660254037844386),
        (-1.0, 0.0),
        (0.0, 0.0),
    ];

    let pts = bug1.to_vec(); // try the other sequences! with bug[1|2]: green vertices, with okay: red (o issue)

    // changing the bounds can make the problem disappear:
    let ((min_x, min_y), (max_x, max_y)) = ((-2.0, -1.86), (1.36, 1.5));
    // let ((min_x, min_y), (max_x, max_y)) = ((-2., -2.), (2., 2.)); // <- with these bounds, no issue

    // with PNG backend this never happened
    let root = BitMapBackend::gif("out.gif", (500, 500), 500)
        .unwrap()
        .into_drawing_area();

    let _ = root.fill(&WHITE);

    let mut cb = ChartBuilder::on(&root);
    let mut chart = cb.build_cartesian_2d(min_x..max_x, min_y..max_y).unwrap();

    // removing either the fill or the border rendering makes the bug disappear:

    // fill area
    let poly = Polygon::new(pts.clone(), &YELLOW.mix(1.0));
    let _ = chart.plotting_area().draw(&poly).unwrap();
    // draw border
    let path = PathElement::new(pts.clone(), &BLACK.mix(1.0));
    let _ = chart.plotting_area().draw(&path).unwrap();

    // vertex marker circles (sometimes rendered in ugly green instead of red)
    let node_func = |c: (f64, f64), s: i32, st: ShapeStyle| {
        EmptyElement::at(c) + Circle::<(i32, i32), i32>::new((0.into(), 0.into()), s.into(), st)
    };
    let nodes = PointSeries::of_element(pts.clone(), 10, RED.mix(1.0).filled(), &node_func);
    chart.draw_series(nodes).unwrap();

    root.present().unwrap();
}

Version Information plotters 0.3.7

apirogov avatar Feb 10 '25 21:02 apirogov