将GooCanvas2保存为PNG文件

时间:2019-03-14 16:55:15

标签: perl gtk3

使用GooCanvas2绘制后,我试图对画布进行“截屏”并将其保存到.PNG文件中。

This script提供了一个使用Gtk2 / GooCanvas的很好的示例,但是将该脚本转换为Gtk3 / GooCanvas2之后,出现了一个我不理解的错误:

send_to_remote(socekt, "msg1")
send_to_remote(socekt, "msg1")

错误是由Gtk3 :: Gdk :: PixbufLoader-> write()生成的。我根本没有修改该功能:

string msg1 = ReadData(client);
string msg2 = ReadData(client);

这是转换后的脚本:

"msg1 (then new line) msg2"
"" (string msg2 is waiting for data)

1 个答案:

答案 0 :(得分:0)

  

*回调中未处理的异常:   * “需要”不是有效的cairo_status_t值;有效值是:成功,无内存,goopng2.pl第90行。   ***无视    在/usr/share/perl5/Gtk3.pm第546行。

通过对代码运行调试器,我可以看到$loader->write($data)引发了异常:

need an array ref to convert to GArray

write_to_png_stream()没想到会出现这种异常,因此将消息截断为第一个单词"need",正如您从顶部的Glib错误消息中所看到的:`need' is not a valid cairo_status_t value ...

通过反复试验,我发现我可以将$buffer参数作为字符数组而不是perl字符串来传递:

sub write_png_clicked {
    my ($but, $canvas) = @_;
    print "Write PNG...\n";

    my $surface = Cairo::ImageSurface->create ('rgb24', 1000, 1000);
    my $cr = Cairo::Context->create($surface);
    $cr->rectangle( 0, 0, 1000, 1000 );
    $cr->set_source_rgb( 1, 1, 1 );
    $cr->fill;
    $canvas->render($cr, undef, 1);
    my $loader = Gtk3::Gdk::PixbufLoader->new;
    $surface->write_to_png_stream (
        sub {
            my ($loader, $buffer) = @_;
            $loader->write([map ord, split //, $buffer]);
            return TRUE;
        }, $loader
    );
    $loader->close;
    my $pixbuf = $loader->get_pixbuf;

    print $pixbuf->get_bits_per_sample(),"\n";
    print $pixbuf->get_colorspace(),"\n";

    $pixbuf->save ("test.png", 'png');
    print "done png\n";
    $pixbuf->save ("test.jpg", 'jpeg', quality => 100); 
    print "done jpg\n";
    return TRUE;
}

修改

要仅保存画布的一部分,可以将GooCanvasBounds参数传递给render()方法:

my $bounds = GooCanvas2::CanvasBounds->new();
$bounds->x1(50);
$bounds->x2(250);
$bounds->y1(50);
$bounds->y2(250);
$canvas->render($cr, $bounds, 1);

编辑2

要捕获特定位置,特定宽度和高度的区域:

my $img_width = 200;
my $img_height = 200;
my $img_x0 = 100;
my $img_y0 = 100;
my $surface = Cairo::ImageSurface->create ('rgb24', $img_width, $img_height);
$cr->translate(-$img_x0,-$img_y0);
$canvas->render($cr, undef, 1);