返回列表 发帖

[原创代码] [POGL]利用 Imager 模块渲染文字

本帖最后由 523066680 于 2018-11-18 11:26 编辑

效果:


之前用 Font::FreeType,真是繁琐。
=info
    Auth: 523066680
    Date: 2018-11
=cut
use utf8;
use Encode;
use feature 'state';
use Time::HiRes qw/time sleep/;
use OpenGL qw/ :all /;
use OpenGL::Config;
use Data::Dumper;
use Imager;
STDOUT->autoflush(1);
our $SIZE_X = 620;
our $SIZE_Y = 520;
our $WinID;
our $pause = 0;
INIT
{
    our $SIZE = 30;
    our $font = Imager::Font->new(file  => encode('gbk', 'C:/windows/fonts/STXINGKA.TTF'), #STXINGKA.TTF
                              size  => $SIZE );
    our $bbox = $font->bounding_box(string=>"");
    our @TEXT = split("", "十步杀一人,千里不留行。事了拂衣去,深藏身与名。" );
    our @TEXT_DATA = map { {} } ( 0 .. $#TEXT );
    for my $id ( 0 .. $#TEXT )
    {
        get_text_map( $TEXT[$id] , $TEXT_DATA[$id] );
        printf "%d %d\n", $TEXT_DATA[$id]->{h}, $TEXT_DATA[$id]->{w};
    }
}
Main();
sub get_text_map
{
    our ($font, $SIZE);
    my ( $char, $ref ) = @_;
    my $bbox = $font->bounding_box( string => $char );
    my $img = Imager->new(xsize=>$bbox->display_width+$bbox->left_bearing,
                          ysize=>$bbox->font_height, channels=>4);
    my $h = $img->getheight();
    my $w = $img->getwidth();
    $img->string(
               font  => $font,
               text  => $char,
               x     => 0,
               y     => $h + $bbox->global_descent,   # 基线 = 总高度 - 下沉
               size  => $SIZE,
               color => 'gold',
               aa    => 1,     # anti-alias
            );
    $ref->{h} = $h, $ref->{w} = $w;
    my @rasters;
    my @colors;
    for my $y ( reverse 0 .. $h - 1 )
    {
        @colors = $img->getpixel( x => [ 0 .. $w - 1 ], y => [$y] );
        grep { push @rasters, $_->rgba  } @colors;
    }
    $ref->{array} = OpenGL::Array->new( scalar( @rasters ), GL_UNSIGNED_BYTE );
    $ref->{array}->assign(0, @rasters);
}
sub display
{
    our ($bbox);
    state $iter = -1;
    my $xbase = 0.0;
    my $ybase = 50.0;
    glClear(GL_COLOR_BUFFER_BIT);
    my $ref;
    for my $id ( 0 .. $iter )
    {
        $ref = $TEXT_DATA[ $id ];
        glRasterPos3f( $xbase , $ybase, 0.0 );
        glDrawPixels_c( $ref->{w}, $ref->{h}, GL_RGBA, GL_UNSIGNED_BYTE, $ref->{array}->ptr() );
        $xbase += $SIZE;
        if ( $TEXT[$id] eq "。" ) { $ybase -= $bbox->font_height , $xbase = 0.0 }
    }
    $iter ++ if ($iter < $#TEXT and $pause == 0);
    glutSwapBuffers();
}
sub init
{
    glClearColor(0.3, 0.6, 0.8, 1.0);
   
    # 通过开启混合,来避免位图的透明背景变黑问题
    glEnable(GL_BLEND);
    #glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
sub idle
{
    sleep 0.2;
    glutPostRedisplay();
}
sub reshape
{
    my ($w, $h) = (shift, shift);
    #Same with screen size
    my $hz_half = $w/2.0;
    my $vt_half = $h/2.0;
    my $fa = 10.0;
    glViewport(0, 0, $w, $h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho( 0.0, $h, 0.0, $w, 0.0, $fa*2.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0,0.0,$fa, 0.0,0.0,0.0, 0.0,1.0, $fa);
}
sub hitkey
{
    my $key = shift;
    glutDestroyWindow($WinID) if ( lc(chr($key)) eq 'q' );
    if ( chr($key) eq 'p' ) { $pause = !$pause; }
}
sub Main
{
    glutInit();
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize($SIZE_X, $SIZE_Y);
    glutInitWindowPosition(5, 100);
    our $WinID = glutCreateWindow("Imager::Font");
    &init();
    glutDisplayFunc(\&display);
    glutKeyboardFunc(\&hitkey);
    glutReshapeFunc(\&reshape);
    glutIdleFunc(\&idle);
    glutMainLoop();
}COPY
2

评分人数

    • CrLf: 好久没给你加技了技术 + 1
    • happy886rr: 好久没给你加技了技术 + 1
[url=][/url]

好一个pogl

TOP

这个厉害了

TOP

本帖最后由 523066680 于 2018-11-21 15:03 编辑

文本渲染
看完这篇后才发现 FreeType也可以直接生成字形的bitmap
face->glyph->bitmap
比起提取轮廓,用Bezier函数细分轮廓曲线,外加三角剖分函数填充,要省事得多。(虽然矢量填充很繁琐,但是缩放起来赏心悦目,哪种方案,视情况而定。)
[url=][/url]

TOP

返回列表