The vector graphics can be scaled without becoming blurred.
Signed-off-by: Leo-Andres Hofmann hofmann@leo-andres.de ---
Hi,
Michael suggested switching to the SVG format for the graphs: https://lists.ipfire.org/pipermail/development/2021-July/010804.html
I have tested this with firefox and chrome, the graphs and error message look fine to me. If someone knows a good SVG validator, I would be happy to get the link :)
Regards, Leo
config/cfgroot/graphs.pl | 2 +- html/cgi-bin/getrrdimage.cgi | 87 +++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 37 deletions(-)
diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 441d4c483..02341eb45 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -40,7 +40,7 @@ my $ERROR;
my @GRAPH_ARGS = ( # Output format - "--imgformat", "PNG", + "--imgformat", "SVG",
# No border "--border", "0", diff --git a/html/cgi-bin/getrrdimage.cgi b/html/cgi-bin/getrrdimage.cgi index c08247c57..92f8b585d 100644 --- a/html/cgi-bin/getrrdimage.cgi +++ b/html/cgi-bin/getrrdimage.cgi @@ -21,8 +21,7 @@
use strict; use URI; -use GD; -use GD::Text::Wrap; +use Text::Wrap; use experimental 'smartmatch';
# debugging @@ -52,7 +51,7 @@ my $range = lc $query{'range'}; # lower case # Check parameters unless(($origin =~ /^\w+?.cgi$/) && ($graph =~ /^[\w-.,; ]+?$/) && ($range ~~ @Graphs::time_ranges)) { # Send HTTP headers - _start_png_output(); + _start_svg_output(); _print_error("URL parameters missing or malformed."); exit; @@ -76,7 +75,7 @@ unless(($origin ~~ @supported_origins) || ($origin eq "getrrdimage.cgi")) {
### Create graphs ### # Send HTTP headers -_start_png_output(); +_start_svg_output();
# Graphs are first grouped by their origin. # This is because some graph categories require special parameter handling. @@ -204,46 +203,62 @@ if($graphstatus) {
###--- Internal functions ---###
-# Send HTTP headers and switch to binary output +# Send HTTP headers # (don't print any non-image data to STDOUT afterwards) -sub _start_png_output { +sub _start_svg_output { print "Cache-Control: no-cache, no-store\n"; - print "Content-Type: image/png\n"; + print "Content-Type: image/svg+xml\n"; print "\n"; # End of HTTP headers - binmode(STDOUT); }
-# Print error message to PNG output +# Print error message to SVG output sub _print_error { my ($message) = @_; - $message = "- Error -\n \n$message"; - - # Create new image with the same size as a graph - my $img = GD::Image->new($Graphs::image_size{'width'}, $Graphs::image_size{'height'}); - $img->interlaced('true'); - - # Basic colors - my $color_background = $img->colorAllocate(255, 255, 255); - my $color_border = $img->colorAllocate(255, 0, 0); - my $color_text = $img->colorAllocate(0, 0, 0);
- # Background and border - $img->setThickness(2); - $img->filledRectangle(0, 0, $img->width, $img->height, $color_background); - $img->rectangle(10, 10, $img->width - 10, $img->height - 10, $color_border); - - # Draw message with line-wrap - my $textbox = GD::Text::Wrap->new($img, - text => $message, - width => ($img->width - 50), - color => $color_text, - align => 'center', - line_space => 5, - preserve_nl => 1 + # Prepare image options + my %img = ( + 'width' => $Graphs::image_size{'width'}, + 'height' => $Graphs::image_size{'height'}, + 'text_center' => int($Graphs::image_size{'width'} / 2), + 'line_height' => 20, + 'font_family' => "DejaVu Sans, Helvetica, sans-serif" # Matching the IPFire theme ); - $textbox->set_font(gdLargeFont); - $textbox->draw(25, 25);
- # Get PNG output - print $img->png; + # Line-wrap message to fit image (adjust to font width if necessary) + local($Text::Wrap::columns) = int($img{'width'} / 10); + $message = wrap('', '', $message); + + # Create new image with fixed background and border + print <<END +<?xml version="1.0" encoding="UTF-8"?> +<svg width="$img{'width'}px" height="$img{'height'}px" viewBox="0 0 $img{'width'} $img{'height'}" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <!-- Background --> + <rect width="100%" height="100%" fill="white"/> + <rect width="100%" height="100%" fill="none" stroke="red" stroke-width="2" transform="scale(0.95)" transform-origin="center"/> + <!-- Message --> + <text x="$img{'text_center'}" y="50" font-size="20" font-family="$img{'font_family'}" text-anchor="middle">- $Lang::tr{'error'} -</text> + <text x="$img{'text_center'}" y="90" font-size="14" font-family="$img{'font_family'}" text-anchor="middle"> +END +; + + # Print message lines + my $shift_y = 0; # Shifts text along y-axis + foreach my $line (split(/\n/, $message)) { + if($line ne "") { # Don't create empty tspan elements + print <<END + <tspan x="$img{'text_center'}" dy="$shift_y">$line</tspan> +END +; + $shift_y = $img{'line_height'}; + } else { # Create blank lines by summing up unused line height + $shift_y += $img{'line_height'}; + } + } + + # Finish SVG output + print <<END + </text> +</svg> +END +; }
No problems found at a quick test with Firefox. Did not check errors, yet.
Reviewed-by: Bernhard Bitsch bbitsch@ipfire.org Tested-by: Bernhard Bitsch bbitsch@ipfire.org
Am 04.08.2021 um 13:01 schrieb Leo-Andres Hofmann:
The vector graphics can be scaled without becoming blurred.
Signed-off-by: Leo-Andres Hofmann hofmann@leo-andres.de
Hi,
Michael suggested switching to the SVG format for the graphs: https://lists.ipfire.org/pipermail/development/2021-July/010804.html
I have tested this with firefox and chrome, the graphs and error message look fine to me. If someone knows a good SVG validator, I would be happy to get the link :)
Regards, Leo
config/cfgroot/graphs.pl | 2 +- html/cgi-bin/getrrdimage.cgi | 87 +++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 37 deletions(-)
diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 441d4c483..02341eb45 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -40,7 +40,7 @@ my $ERROR;
my @GRAPH_ARGS = ( # Output format
- "--imgformat", "PNG",
"--imgformat", "SVG",
# No border "--border", "0",
diff --git a/html/cgi-bin/getrrdimage.cgi b/html/cgi-bin/getrrdimage.cgi index c08247c57..92f8b585d 100644 --- a/html/cgi-bin/getrrdimage.cgi +++ b/html/cgi-bin/getrrdimage.cgi @@ -21,8 +21,7 @@
use strict; use URI; -use GD; -use GD::Text::Wrap; +use Text::Wrap; use experimental 'smartmatch';
# debugging @@ -52,7 +51,7 @@ my $range = lc $query{'range'}; # lower case # Check parameters unless(($origin =~ /^\w+?.cgi$/) && ($graph =~ /^[\w-.,; ]+?$/) && ($range ~~ @Graphs::time_ranges)) { # Send HTTP headers
- _start_png_output();
_start_svg_output();
_print_error("URL parameters missing or malformed."); exit;
@@ -76,7 +75,7 @@ unless(($origin ~~ @supported_origins) || ($origin eq "getrrdimage.cgi")) {
### Create graphs ### # Send HTTP headers -_start_png_output(); +_start_svg_output();
# Graphs are first grouped by their origin. # This is because some graph categories require special parameter handling. @@ -204,46 +203,62 @@ if($graphstatus) {
###--- Internal functions ---###
-# Send HTTP headers and switch to binary output +# Send HTTP headers # (don't print any non-image data to STDOUT afterwards) -sub _start_png_output { +sub _start_svg_output { print "Cache-Control: no-cache, no-store\n";
- print "Content-Type: image/png\n";
- print "Content-Type: image/svg+xml\n"; print "\n"; # End of HTTP headers
- binmode(STDOUT); }
-# Print error message to PNG output +# Print error message to SVG output sub _print_error { my ($message) = @_;
$message = "- Error -\n \n$message";
# Create new image with the same size as a graph
my $img = GD::Image->new($Graphs::image_size{'width'}, $Graphs::image_size{'height'});
$img->interlaced('true');
# Basic colors
my $color_background = $img->colorAllocate(255, 255, 255);
my $color_border = $img->colorAllocate(255, 0, 0);
my $color_text = $img->colorAllocate(0, 0, 0);
# Background and border
$img->setThickness(2);
$img->filledRectangle(0, 0, $img->width, $img->height, $color_background);
$img->rectangle(10, 10, $img->width - 10, $img->height - 10, $color_border);
# Draw message with line-wrap
my $textbox = GD::Text::Wrap->new($img,
text => $message,
width => ($img->width - 50),
color => $color_text,
align => 'center',
line_space => 5,
preserve_nl => 1
- # Prepare image options
- my %img = (
'width' => $Graphs::image_size{'width'},
'height' => $Graphs::image_size{'height'},
'text_center' => int($Graphs::image_size{'width'} / 2),
'line_height' => 20,
);'font_family' => "DejaVu Sans, Helvetica, sans-serif" # Matching the IPFire theme
$textbox->set_font(gdLargeFont);
$textbox->draw(25, 25);
# Get PNG output
print $img->png;
- # Line-wrap message to fit image (adjust to font width if necessary)
- local($Text::Wrap::columns) = int($img{'width'} / 10);
- $message = wrap('', '', $message);
- # Create new image with fixed background and border
- print <<END
+<?xml version="1.0" encoding="UTF-8"?> +<svg width="$img{'width'}px" height="$img{'height'}px" viewBox="0 0 $img{'width'} $img{'height'}" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- Background -->
<rect width="100%" height="100%" fill="white"/>
<rect width="100%" height="100%" fill="none" stroke="red" stroke-width="2" transform="scale(0.95)" transform-origin="center"/>
<!-- Message -->
- <text x="$img{'text_center'}" y="50" font-size="20" font-family="$img{'font_family'}" text-anchor="middle">- $Lang::tr{'error'} -</text>
<text x="$img{'text_center'}" y="90" font-size="14" font-family="$img{'font_family'}" text-anchor="middle">
+END +;
- # Print message lines
- my $shift_y = 0; # Shifts text along y-axis
- foreach my $line (split(/\n/, $message)) {
if($line ne "") { # Don't create empty tspan elements
print <<END
<tspan x="$img{'text_center'}" dy="$shift_y">$line</tspan>
+END +;
$shift_y = $img{'line_height'};
} else { # Create blank lines by summing up unused line height
$shift_y += $img{'line_height'};
}
- }
- # Finish SVG output
- print <<END
</text>
+</svg> +END +; }
Cool. Thank you.
Did you test if the SVG files can be generated quicker than PNG?
-Michael
On 4 Aug 2021, at 13:01, Leo-Andres Hofmann hofmann@leo-andres.de wrote:
The vector graphics can be scaled without becoming blurred.
Signed-off-by: Leo-Andres Hofmann hofmann@leo-andres.de
Hi,
Michael suggested switching to the SVG format for the graphs: https://lists.ipfire.org/pipermail/development/2021-July/010804.html
I have tested this with firefox and chrome, the graphs and error message look fine to me. If someone knows a good SVG validator, I would be happy to get the link :)
Regards, Leo
config/cfgroot/graphs.pl | 2 +- html/cgi-bin/getrrdimage.cgi | 87 +++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 37 deletions(-)
diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 441d4c483..02341eb45 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -40,7 +40,7 @@ my $ERROR;
my @GRAPH_ARGS = ( # Output format
- "--imgformat", "PNG",
"--imgformat", "SVG",
# No border "--border", "0",
diff --git a/html/cgi-bin/getrrdimage.cgi b/html/cgi-bin/getrrdimage.cgi index c08247c57..92f8b585d 100644 --- a/html/cgi-bin/getrrdimage.cgi +++ b/html/cgi-bin/getrrdimage.cgi @@ -21,8 +21,7 @@
use strict; use URI; -use GD; -use GD::Text::Wrap; +use Text::Wrap; use experimental 'smartmatch';
# debugging @@ -52,7 +51,7 @@ my $range = lc $query{'range'}; # lower case # Check parameters unless(($origin =~ /^\w+?.cgi$/) && ($graph =~ /^[\w-.,; ]+?$/) && ($range ~~ @Graphs::time_ranges)) { # Send HTTP headers
- _start_png_output();
_start_svg_output();
_print_error("URL parameters missing or malformed."); exit;
@@ -76,7 +75,7 @@ unless(($origin ~~ @supported_origins) || ($origin eq "getrrdimage.cgi")) {
### Create graphs ### # Send HTTP headers -_start_png_output(); +_start_svg_output();
# Graphs are first grouped by their origin. # This is because some graph categories require special parameter handling. @@ -204,46 +203,62 @@ if($graphstatus) {
###--- Internal functions ---###
-# Send HTTP headers and switch to binary output +# Send HTTP headers # (don't print any non-image data to STDOUT afterwards) -sub _start_png_output { +sub _start_svg_output { print "Cache-Control: no-cache, no-store\n";
- print "Content-Type: image/png\n";
- print "Content-Type: image/svg+xml\n"; print "\n"; # End of HTTP headers
- binmode(STDOUT);
}
-# Print error message to PNG output +# Print error message to SVG output sub _print_error { my ($message) = @_;
$message = "- Error -\n \n$message";
# Create new image with the same size as a graph
my $img = GD::Image->new($Graphs::image_size{'width'}, $Graphs::image_size{'height'});
$img->interlaced('true');
# Basic colors
my $color_background = $img->colorAllocate(255, 255, 255);
my $color_border = $img->colorAllocate(255, 0, 0);
my $color_text = $img->colorAllocate(0, 0, 0);
# Background and border
$img->setThickness(2);
$img->filledRectangle(0, 0, $img->width, $img->height, $color_background);
$img->rectangle(10, 10, $img->width - 10, $img->height - 10, $color_border);
# Draw message with line-wrap
my $textbox = GD::Text::Wrap->new($img,
text => $message,
width => ($img->width - 50),
color => $color_text,
align => 'center',
line_space => 5,
preserve_nl => 1
- # Prepare image options
- my %img = (
'width' => $Graphs::image_size{'width'},
'height' => $Graphs::image_size{'height'},
'text_center' => int($Graphs::image_size{'width'} / 2),
'line_height' => 20,
);'font_family' => "DejaVu Sans, Helvetica, sans-serif" # Matching the IPFire theme
$textbox->set_font(gdLargeFont);
$textbox->draw(25, 25);
# Get PNG output
print $img->png;
- # Line-wrap message to fit image (adjust to font width if necessary)
- local($Text::Wrap::columns) = int($img{'width'} / 10);
- $message = wrap('', '', $message);
- # Create new image with fixed background and border
- print <<END
+<?xml version="1.0" encoding="UTF-8"?> +<svg width="$img{'width'}px" height="$img{'height'}px" viewBox="0 0 $img{'width'} $img{'height'}" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- Background -->
<rect width="100%" height="100%" fill="white"/>
<rect width="100%" height="100%" fill="none" stroke="red" stroke-width="2" transform="scale(0.95)" transform-origin="center"/>
<!-- Message -->
- <text x="$img{'text_center'}" y="50" font-size="20" font-family="$img{'font_family'}" text-anchor="middle">- $Lang::tr{'error'} -</text>
<text x="$img{'text_center'}" y="90" font-size="14" font-family="$img{'font_family'}" text-anchor="middle">
+END +;
- # Print message lines
- my $shift_y = 0; # Shifts text along y-axis
- foreach my $line (split(/\n/, $message)) {
if($line ne "") { # Don't create empty tspan elements
print <<END
<tspan x="$img{'text_center'}" dy="$shift_y">$line</tspan>
+END +;
$shift_y = $img{'line_height'};
} else { # Create blank lines by summing up unused line height
$shift_y += $img{'line_height'};
}
- }
- # Finish SVG output
- print <<END
</text>
+</svg> +END +; } -- 2.27.0.windows.1
Am 04.08.2021 um 16:40 schrieb Michael Tremer:
Cool. Thank you.
Did you test if the SVG files can be generated quicker than PNG?
Haven't measured in detail, but the time for display of the graph seems equal to the png pictures ( on my small ALIX ). But I didn't check the timings of sampling of the data also.
- Bernhard
-Michael
On 4 Aug 2021, at 13:01, Leo-Andres Hofmann hofmann@leo-andres.de wrote:
The vector graphics can be scaled without becoming blurred.
Signed-off-by: Leo-Andres Hofmann hofmann@leo-andres.de
Hi,
Michael suggested switching to the SVG format for the graphs: https://lists.ipfire.org/pipermail/development/2021-July/010804.html
I have tested this with firefox and chrome, the graphs and error message look fine to me. If someone knows a good SVG validator, I would be happy to get the link :)
Regards, Leo
config/cfgroot/graphs.pl | 2 +- html/cgi-bin/getrrdimage.cgi | 87 +++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 37 deletions(-)
diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 441d4c483..02341eb45 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -40,7 +40,7 @@ my $ERROR;
my @GRAPH_ARGS = ( # Output format
- "--imgformat", "PNG",
"--imgformat", "SVG",
# No border "--border", "0",
diff --git a/html/cgi-bin/getrrdimage.cgi b/html/cgi-bin/getrrdimage.cgi index c08247c57..92f8b585d 100644 --- a/html/cgi-bin/getrrdimage.cgi +++ b/html/cgi-bin/getrrdimage.cgi @@ -21,8 +21,7 @@
use strict; use URI; -use GD; -use GD::Text::Wrap; +use Text::Wrap; use experimental 'smartmatch';
# debugging @@ -52,7 +51,7 @@ my $range = lc $query{'range'}; # lower case # Check parameters unless(($origin =~ /^\w+?.cgi$/) && ($graph =~ /^[\w-.,; ]+?$/) && ($range ~~ @Graphs::time_ranges)) { # Send HTTP headers
- _start_png_output();
_start_svg_output();
_print_error("URL parameters missing or malformed."); exit;
@@ -76,7 +75,7 @@ unless(($origin ~~ @supported_origins) || ($origin eq "getrrdimage.cgi")) {
### Create graphs ### # Send HTTP headers -_start_png_output(); +_start_svg_output();
# Graphs are first grouped by their origin. # This is because some graph categories require special parameter handling. @@ -204,46 +203,62 @@ if($graphstatus) {
###--- Internal functions ---###
-# Send HTTP headers and switch to binary output +# Send HTTP headers # (don't print any non-image data to STDOUT afterwards) -sub _start_png_output { +sub _start_svg_output { print "Cache-Control: no-cache, no-store\n";
- print "Content-Type: image/png\n";
- print "Content-Type: image/svg+xml\n"; print "\n"; # End of HTTP headers
- binmode(STDOUT);
}
-# Print error message to PNG output +# Print error message to SVG output sub _print_error { my ($message) = @_;
$message = "- Error -\n \n$message";
# Create new image with the same size as a graph
my $img = GD::Image->new($Graphs::image_size{'width'}, $Graphs::image_size{'height'});
$img->interlaced('true');
# Basic colors
my $color_background = $img->colorAllocate(255, 255, 255);
my $color_border = $img->colorAllocate(255, 0, 0);
my $color_text = $img->colorAllocate(0, 0, 0);
# Background and border
$img->setThickness(2);
$img->filledRectangle(0, 0, $img->width, $img->height, $color_background);
$img->rectangle(10, 10, $img->width - 10, $img->height - 10, $color_border);
# Draw message with line-wrap
my $textbox = GD::Text::Wrap->new($img,
text => $message,
width => ($img->width - 50),
color => $color_text,
align => 'center',
line_space => 5,
preserve_nl => 1
- # Prepare image options
- my %img = (
'width' => $Graphs::image_size{'width'},
'height' => $Graphs::image_size{'height'},
'text_center' => int($Graphs::image_size{'width'} / 2),
'line_height' => 20,
);'font_family' => "DejaVu Sans, Helvetica, sans-serif" # Matching the IPFire theme
$textbox->set_font(gdLargeFont);
$textbox->draw(25, 25);
# Get PNG output
print $img->png;
- # Line-wrap message to fit image (adjust to font width if necessary)
- local($Text::Wrap::columns) = int($img{'width'} / 10);
- $message = wrap('', '', $message);
- # Create new image with fixed background and border
- print <<END
+<?xml version="1.0" encoding="UTF-8"?> +<svg width="$img{'width'}px" height="$img{'height'}px" viewBox="0 0 $img{'width'} $img{'height'}" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- Background -->
<rect width="100%" height="100%" fill="white"/>
<rect width="100%" height="100%" fill="none" stroke="red" stroke-width="2" transform="scale(0.95)" transform-origin="center"/>
<!-- Message -->
- <text x="$img{'text_center'}" y="50" font-size="20" font-family="$img{'font_family'}" text-anchor="middle">- $Lang::tr{'error'} -</text>
<text x="$img{'text_center'}" y="90" font-size="14" font-family="$img{'font_family'}" text-anchor="middle">
+END +;
- # Print message lines
- my $shift_y = 0; # Shifts text along y-axis
- foreach my $line (split(/\n/, $message)) {
if($line ne "") { # Don't create empty tspan elements
print <<END
<tspan x="$img{'text_center'}" dy="$shift_y">$line</tspan>
+END +;
$shift_y = $img{'line_height'};
} else { # Create blank lines by summing up unused line height
$shift_y += $img{'line_height'};
}
- }
- # Finish SVG output
- print <<END
</text>
+</svg> +END +; } -- 2.27.0.windows.1
I used the Firefox developer tools to check the loading times of the images.
On average, the SVG image is generated 10ms faster: "HTTP Wait" for PNG: ~126ms, for SVG: ~115ms (My test system: Core 159 on Proxmox VM/Xeon 3,3GHz)
Regards, Leo
Am 04.08.2021 um 16:40 schrieb Michael Tremer:
Cool. Thank you.
Did you test if the SVG files can be generated quicker than PNG?
-Michael
On 4 Aug 2021, at 13:01, Leo-Andres Hofmann hofmann@leo-andres.de wrote:
The vector graphics can be scaled without becoming blurred.
Signed-off-by: Leo-Andres Hofmann hofmann@leo-andres.de
Hi,
Michael suggested switching to the SVG format for the graphs: https://lists.ipfire.org/pipermail/development/2021-July/010804.html
I have tested this with firefox and chrome, the graphs and error message look fine to me. If someone knows a good SVG validator, I would be happy to get the link :)
Regards, Leo
config/cfgroot/graphs.pl | 2 +- html/cgi-bin/getrrdimage.cgi | 87 +++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 37 deletions(-)
diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 441d4c483..02341eb45 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -40,7 +40,7 @@ my $ERROR;
my @GRAPH_ARGS = ( # Output format
- "--imgformat", "PNG",
"--imgformat", "SVG",
# No border "--border", "0",
diff --git a/html/cgi-bin/getrrdimage.cgi b/html/cgi-bin/getrrdimage.cgi index c08247c57..92f8b585d 100644 --- a/html/cgi-bin/getrrdimage.cgi +++ b/html/cgi-bin/getrrdimage.cgi @@ -21,8 +21,7 @@
use strict; use URI; -use GD; -use GD::Text::Wrap; +use Text::Wrap; use experimental 'smartmatch';
# debugging @@ -52,7 +51,7 @@ my $range = lc $query{'range'}; # lower case # Check parameters unless(($origin =~ /^\w+?.cgi$/) && ($graph =~ /^[\w-.,; ]+?$/) && ($range ~~ @Graphs::time_ranges)) { # Send HTTP headers
- _start_png_output();
_start_svg_output();
_print_error("URL parameters missing or malformed."); exit;
@@ -76,7 +75,7 @@ unless(($origin ~~ @supported_origins) || ($origin eq "getrrdimage.cgi")) {
### Create graphs ### # Send HTTP headers -_start_png_output(); +_start_svg_output();
# Graphs are first grouped by their origin. # This is because some graph categories require special parameter handling. @@ -204,46 +203,62 @@ if($graphstatus) {
###--- Internal functions ---###
-# Send HTTP headers and switch to binary output +# Send HTTP headers # (don't print any non-image data to STDOUT afterwards) -sub _start_png_output { +sub _start_svg_output { print "Cache-Control: no-cache, no-store\n";
- print "Content-Type: image/png\n";
- print "Content-Type: image/svg+xml\n"; print "\n"; # End of HTTP headers
- binmode(STDOUT);
}
-# Print error message to PNG output +# Print error message to SVG output sub _print_error { my ($message) = @_;
$message = "- Error -\n \n$message";
# Create new image with the same size as a graph
my $img = GD::Image->new($Graphs::image_size{'width'}, $Graphs::image_size{'height'});
$img->interlaced('true');
# Basic colors
my $color_background = $img->colorAllocate(255, 255, 255);
my $color_border = $img->colorAllocate(255, 0, 0);
my $color_text = $img->colorAllocate(0, 0, 0);
# Background and border
$img->setThickness(2);
$img->filledRectangle(0, 0, $img->width, $img->height, $color_background);
$img->rectangle(10, 10, $img->width - 10, $img->height - 10, $color_border);
# Draw message with line-wrap
my $textbox = GD::Text::Wrap->new($img,
text => $message,
width => ($img->width - 50),
color => $color_text,
align => 'center',
line_space => 5,
preserve_nl => 1
- # Prepare image options
- my %img = (
'width' => $Graphs::image_size{'width'},
'height' => $Graphs::image_size{'height'},
'text_center' => int($Graphs::image_size{'width'} / 2),
'line_height' => 20,
);'font_family' => "DejaVu Sans, Helvetica, sans-serif" # Matching the IPFire theme
$textbox->set_font(gdLargeFont);
$textbox->draw(25, 25);
# Get PNG output
print $img->png;
- # Line-wrap message to fit image (adjust to font width if necessary)
- local($Text::Wrap::columns) = int($img{'width'} / 10);
- $message = wrap('', '', $message);
- # Create new image with fixed background and border
- print <<END
+<?xml version="1.0" encoding="UTF-8"?> +<svg width="$img{'width'}px" height="$img{'height'}px" viewBox="0 0 $img{'width'} $img{'height'}" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- Background -->
<rect width="100%" height="100%" fill="white"/>
<rect width="100%" height="100%" fill="none" stroke="red" stroke-width="2" transform="scale(0.95)" transform-origin="center"/>
<!-- Message -->
- <text x="$img{'text_center'}" y="50" font-size="20" font-family="$img{'font_family'}" text-anchor="middle">- $Lang::tr{'error'} -</text>
<text x="$img{'text_center'}" y="90" font-size="14" font-family="$img{'font_family'}" text-anchor="middle">
+END +;
- # Print message lines
- my $shift_y = 0; # Shifts text along y-axis
- foreach my $line (split(/\n/, $message)) {
if($line ne "") { # Don't create empty tspan elements
print <<END
<tspan x="$img{'text_center'}" dy="$shift_y">$line</tspan>
+END +;
$shift_y = $img{'line_height'};
} else { # Create blank lines by summing up unused line height
$shift_y += $img{'line_height'};
}
- }
- # Finish SVG output
- print <<END
</text>
+</svg> +END +; } -- 2.27.0.windows.1
Hello Leo,
On 5 Aug 2021, at 10:40, Leo Hofmann hofmann@leo-andres.de wrote:
I used the Firefox developer tools to check the loading times of the images.
On average, the SVG image is generated 10ms faster: "HTTP Wait" for PNG: ~126ms, for SVG: ~115ms (My test system: Core 159 on Proxmox VM/Xeon 3,3GHz)
Okay. That seems to be a good improvement then. Around 10%. Cool.
-Michael
Regards, Leo
Am 04.08.2021 um 16:40 schrieb Michael Tremer:
Cool. Thank you.
Did you test if the SVG files can be generated quicker than PNG?
-Michael
On 4 Aug 2021, at 13:01, Leo-Andres Hofmann hofmann@leo-andres.de wrote:
The vector graphics can be scaled without becoming blurred.
Signed-off-by: Leo-Andres Hofmann hofmann@leo-andres.de
Hi,
Michael suggested switching to the SVG format for the graphs: https://lists.ipfire.org/pipermail/development/2021-July/010804.html
I have tested this with firefox and chrome, the graphs and error message look fine to me. If someone knows a good SVG validator, I would be happy to get the link :)
Regards, Leo
config/cfgroot/graphs.pl | 2 +- html/cgi-bin/getrrdimage.cgi | 87 +++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 37 deletions(-)
diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 441d4c483..02341eb45 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -40,7 +40,7 @@ my $ERROR;
my @GRAPH_ARGS = ( # Output format
- "--imgformat", "PNG",
"--imgformat", "SVG",
# No border "--border", "0",
diff --git a/html/cgi-bin/getrrdimage.cgi b/html/cgi-bin/getrrdimage.cgi index c08247c57..92f8b585d 100644 --- a/html/cgi-bin/getrrdimage.cgi +++ b/html/cgi-bin/getrrdimage.cgi @@ -21,8 +21,7 @@
use strict; use URI; -use GD; -use GD::Text::Wrap; +use Text::Wrap; use experimental 'smartmatch';
# debugging @@ -52,7 +51,7 @@ my $range = lc $query{'range'}; # lower case # Check parameters unless(($origin =~ /^\w+?.cgi$/) && ($graph =~ /^[\w-.,; ]+?$/) && ($range ~~ @Graphs::time_ranges)) { # Send HTTP headers
- _start_png_output();
_start_svg_output();
_print_error("URL parameters missing or malformed."); exit;
@@ -76,7 +75,7 @@ unless(($origin ~~ @supported_origins) || ($origin eq "getrrdimage.cgi")) {
### Create graphs ### # Send HTTP headers -_start_png_output(); +_start_svg_output();
# Graphs are first grouped by their origin. # This is because some graph categories require special parameter handling. @@ -204,46 +203,62 @@ if($graphstatus) {
###--- Internal functions ---###
-# Send HTTP headers and switch to binary output +# Send HTTP headers # (don't print any non-image data to STDOUT afterwards) -sub _start_png_output { +sub _start_svg_output { print "Cache-Control: no-cache, no-store\n";
- print "Content-Type: image/png\n";
- print "Content-Type: image/svg+xml\n"; print "\n"; # End of HTTP headers
- binmode(STDOUT);
}
-# Print error message to PNG output +# Print error message to SVG output sub _print_error { my ($message) = @_;
$message = "- Error -\n \n$message";
# Create new image with the same size as a graph
my $img = GD::Image->new($Graphs::image_size{'width'}, $Graphs::image_size{'height'});
$img->interlaced('true');
# Basic colors
my $color_background = $img->colorAllocate(255, 255, 255);
my $color_border = $img->colorAllocate(255, 0, 0);
my $color_text = $img->colorAllocate(0, 0, 0);
# Background and border
$img->setThickness(2);
$img->filledRectangle(0, 0, $img->width, $img->height, $color_background);
$img->rectangle(10, 10, $img->width - 10, $img->height - 10, $color_border);
# Draw message with line-wrap
my $textbox = GD::Text::Wrap->new($img,
text => $message,
width => ($img->width - 50),
color => $color_text,
align => 'center',
line_space => 5,
preserve_nl => 1
- # Prepare image options
- my %img = (
'width' => $Graphs::image_size{'width'},
'height' => $Graphs::image_size{'height'},
'text_center' => int($Graphs::image_size{'width'} / 2),
'line_height' => 20,
);'font_family' => "DejaVu Sans, Helvetica, sans-serif" # Matching the IPFire theme
$textbox->set_font(gdLargeFont);
$textbox->draw(25, 25);
# Get PNG output
print $img->png;
- # Line-wrap message to fit image (adjust to font width if necessary)
- local($Text::Wrap::columns) = int($img{'width'} / 10);
- $message = wrap('', '', $message);
- # Create new image with fixed background and border
- print <<END
+<?xml version="1.0" encoding="UTF-8"?> +<svg width="$img{'width'}px" height="$img{'height'}px" viewBox="0 0 $img{'width'} $img{'height'}" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- Background -->
<rect width="100%" height="100%" fill="white"/>
<rect width="100%" height="100%" fill="none" stroke="red" stroke-width="2" transform="scale(0.95)" transform-origin="center"/>
<!-- Message -->
- <text x="$img{'text_center'}" y="50" font-size="20" font-family="$img{'font_family'}" text-anchor="middle">- $Lang::tr{'error'} -</text>
<text x="$img{'text_center'}" y="90" font-size="14" font-family="$img{'font_family'}" text-anchor="middle">
+END +;
- # Print message lines
- my $shift_y = 0; # Shifts text along y-axis
- foreach my $line (split(/\n/, $message)) {
if($line ne "") { # Don't create empty tspan elements
print <<END
<tspan x="$img{'text_center'}" dy="$shift_y">$line</tspan>
+END +;
$shift_y = $img{'line_height'};
} else { # Create blank lines by summing up unused line height
$shift_y += $img{'line_height'};
}
- }
- # Finish SVG output
- print <<END
</text>
+</svg> +END +; } -- 2.27.0.windows.1