首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将GooCanvas2保存到PNG文件

将GooCanvas2保存到PNG文件
EN

Stack Overflow用户
提问于 2019-03-14 16:55:14
回答 1查看 96关注 0票数 2

使用GooCanvas2绘图后,我尝试获取画布的“屏幕截图”,并将其保存到.PNG文件中。

这个剧本提供了一个使用Gtk2 2/GooCanvas的非常好的示例,但是在将该脚本转换为Gtk2 3/GooCanvas2之后,我得到了一个我不明白的错误:

代码语言:javascript
复制
Write PNG...
*** unhandled exception in callback:
***   `need' is not a valid cairo_status_t value; valid values are: success, no-memory, invalid-restore, invalid-pop-group, no-current-point, invalid-matrix, invalid-status, null-pointer, invalid-string, invalid-path-data, read-error, write-error, surface-finished, surface-type-mismatch, pattern-type-mismatch, invalid-content, invalid-format, invalid-visual, file-not-found, invalid-dash, invalid-dsc-comment, invalid-index, clip-not-representable, temp-file-error, invalid-stride, font-type-mismatch, user-font-immutable, user-font-error, negative-count, invalid-clusters, invalid-slant, invalid-weight at goopng2.pl line 90.
***  ignoring at /usr/share/perl5/Gtk3.pm line 546.

错误由Gtk3 3::Gdk::PixbufLoader->write()生成。我根本没有修改这一职能:

代码语言:javascript
复制
$surface->write_to_png_stream (sub {
    my ($closure, $data) = @_;
    $loader->write($data);
});

这是转换后的脚本:

代码语言:javascript
复制
#!/usr/bin/perl -w
use strict;

use warnings;
use GooCanvas2;
use Gtk3 '-init';
use Glib qw(TRUE FALSE);

my $window = Gtk3::Window->new('toplevel');
$window->signal_connect('delete_event' => sub { Gtk3->main_quit; });
$window->set_default_size(640, 600);


my $vbox = Gtk3::VBox->new;
$vbox->set_border_width(4);
$vbox->show;
$window->add($vbox);

my $swin = Gtk3::ScrolledWindow->new;
$swin->set_shadow_type('in');
$vbox->pack_start($swin, 1, 1, 0); 

my $canvas = GooCanvas2::Canvas->new();
$canvas->set_size_request(600, 450);
$canvas->set_bounds(0, 0, 1000, 1000);
$swin->add($canvas);

my $root = $canvas->get_root_item();

my $rect = GooCanvas2::CanvasRect->new(
    parent => $root,
    'x' => 100,
    'y' => 100,
    'width' => 400,
    'height' => 400,
    'line-width' => 10,
    'radius-x' => 20,
    'radius-y' => 10,
    'stroke-color' => 'yellow',
    'fill-color' => 'red'
);

my $text = GooCanvas2::CanvasText->new(
    'parent' => $root,
    'text' => "Hello World",
    'x' => 300,
    'y' => 300,
    'width' => -1,
    'anchor' => 'center',
    'font' => 'Sans 24',
);
$text->rotate(45, 300, 300);

# Create PNG                                                                          
my $sb = Gtk3::Button->new_with_label('Write PNG and JPG');                                       
$vbox->pack_start($sb, FALSE, FALSE, 0);                                               
$sb->show;                                                                             
$sb->signal_connect("clicked", \&write_png_clicked, $canvas);                          

$window->show_all();
Gtk3->main;

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

    my $surface = Cairo::ImageSurface->create ('rgb24', 1000, 1000);
    # also argb32 is available
    # my $surface = Cairo::ImageSurface->create ('argb32', 1000, 1000);

    my $cr = Cairo::Context->create($surface);

    # make a background rectangle filled white so saved file looks same as screen
    # otherwise a black background may appear, it's like pdf, if it isn't
    # drawn , it will be a black background, It won't automagically pick up
    # a white background on a canvas
    $cr->rectangle( 0, 0, 1000, 1000 );
    $cr->set_source_rgb( 1, 1, 1 );
    $cr->fill;

    $canvas->render($cr, undef, 1);

    # this works, but see below for way to use pixbuf and jpg
    #    my $status = $surface->write_to_png ("$0.png");
    #    print "$status\n";

    my $loader = Gtk3::Gdk::PixbufLoader->new;
        $surface->write_to_png_stream (sub {
        my ($closure, $data) = @_;
        $loader->write($data);
    });
    $loader->close;
    my $pixbuf = $loader->get_pixbuf;

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

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

    return TRUE;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-14 22:19:46

*回调中未处理的异常:*‘cairo_status_t’不是有效的cairo_status_t值;有效值是:成功、无内存、.在goopng2.pl第90行。*忽略/usr/share/perl5 5/gtk3.pm第546行。

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

代码语言:javascript
复制
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字符串:

代码语言:javascript
复制
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()方法:

代码语言:javascript
复制
my $bounds = GooCanvas2::CanvasBounds->new();
$bounds->x1(50);
$bounds->x2(250);
$bounds->y1(50);
$bounds->y2(250);
$canvas->render($cr, $bounds, 1);

编辑2

捕捉特定位置和特定宽度和高度的区域:

代码语言:javascript
复制
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);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55168126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档