PChart linear chart image quality
Asked Answered
T

2

14

I am using PChart to create linear charts. Everything goes well beside the quality of the actual lines drawn.

Of course, antialiasing is not turned off, and even explicitly turned on.

Here is an example of the actual image, which looks quite ugly with all these steps.

enter image description here

Is there a way to make the lines drawn smoother, without stepping?

The code used:

public function linearTwoAxis($data, $fileName, $startColor = 0)
{
    $pData = new \pData();

    $i = 0;
    foreach ($data as $key => $row)
    {
        $serie = $this->translator->trans("pages.reportDefault.$key");
        $pData->addPoints($row, $serie);
        $pData->setSerieOnAxis($serie, $i);
        $pData->setSerieWeight($serie, 1);
        $pData->setAxisName($i, $serie);
        $pData->setPalette($serie, $this->colors[$startColor++]);
        $pData->setAxisDisplay($i, AXIS_FORMAT_METRIC);
        $i++;
    }
    $monthNames = array_keys($row);

    $pData->setAxisPosition(1, AXIS_POSITION_RIGHT);
    $pData->addPoints($monthNames, "Labels");
    $pData->setAbscissa("Labels");

    $pChart = new \pImage(750, 200, $pData);

    $pChart->setFontProperties(array(
        "FontName" => $this->fonts_dir . "arial.ttf",
        "FontSize" => 8)
    );

    $pChart->setGraphArea(50, 10, 700, 150);
    $pChart->Antialias = TRUE;
    $pChart->drawScale(["Mode"  => SCALE_MODE_START0]);
    $pChart->drawLineChart();
    $pChart->drawLegend(325,180,array("Style"=>LEGEND_BOX,"Mode"=>LEGEND_HORIZONTAL, "BoxWidth"=>30,"Family"=>LEGEND_FAMILY_LINE,"Alpha" => 0));

    $pChart->render($this->target_dir . $fileName);

    return $this->target_dirname . $fileName;
}
Tow answered 27/9, 2016 at 13:0 Comment(2)
pchart.sourceforge.net/documentation.php?topic=advexemple16 . may this helps youNealey
Does the problem persist when you remove $pData->setSerieWeight($serie, 1);?Dodecasyllable
A
4

If nothing else helps draw the chart much larger and then scale down the resulting image with ImageMagick. This is a last resort solution which has an obvious additional computation cost.

That's an example line:

convert chart.png -resize 750×200 chart.jpg

If the original image is twice as large (by simply doubling both dimensions you have in your code) a resize like this would collapse four pixels into one, smoothing out jaggies on five levels (0%, 25%, 50%, 75%, 100%). If you draw the image even larger you may switch off anti aliasing when drawing the lines, because the resizing will smooth out everything anyways.

Fonts and readability may become a problem, so maybe you want to draw two images:

  • just the lines on a larger scale;
  • the remaining legend/rulers and such on the original scale.

After resizing the line image, you then have to combine both images by overlapping them into one single image. This can be done with ImageMagick, too.

Applewhite answered 14/10, 2016 at 19:31 Comment(2)
It is not a matter of resize. It's a matter of generating the initial image. pChart takes A LOT of time to generate a bigger image. JFYITow
That's what I thought. But I had to give it a try :)Applewhite
F
2

If you remove setSerieWeight it produces much better antialiasing. For example.

<?php 

require_once "class/pDraw.class.php"; require_once "class/pImage.class.php"; require_once "class/pData.class.php";

$pData = new \pData();

$data = array(array(0,100),array(100,200),array(200,500)); 



    $i = 0;
    foreach ($data as $key => $row)
    {
        $serie = 'test';
        $pData->addPoints($row, $serie);
        $pData->setSerieOnAxis($serie, $i);

        $pData->setAxisName($i, $serie);
        $pData->setPalette($serie,  array("R"=>74,"G"=>42,"B"=>112,"Alpha"=>100));
        $pData->setAxisDisplay($i, AXIS_FORMAT_METRIC);
        $i++;
    }
    $monthNames = array_keys($row);



    $pChart = new \pImage(750, 200, $pData);

    $pChart->setFontProperties(array(
        "FontName" =>  "arial.ttf",
        "FontSize" => 8)
    );

    $pChart->setGraphArea(50, 10, 700, 150);
    $pChart->Antialias = TRUE;
    $pChart->drawScale(["Mode"  => SCALE_MODE_START0]);
    $pChart->drawLineChart();
    $pChart->drawLegend(325,180,array("Style"=>LEGEND_BOX,"Mode"=>LEGEND_HORIZONTAL, "BoxWidth"=>30,"Family"=>LEGEND_FAMILY_LINE,"Alpha" => 0));

    $pChart->render('test.png');

enter image description here

Fowlkes answered 18/10, 2016 at 11:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.