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;
}
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345

2 Answers2

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.

pid
  • 11,472
  • 6
  • 34
  • 63
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

Pawel Dubiel
  • 18,665
  • 3
  • 40
  • 58