3

我用 MoviePy 和 Gizeh 创建了一个文本缩放动画。但是,当代码在不同的操作系统上运行时,结果会有所不同。以下两个gif是由相同的python代码生成的。效果在 MacOS 上看起来还不错,但在 Linux 上效果很差。

在 MacOS 上相当不错

在 MacOS 上相当不错

Linux 上的颤抖效果

Linux 上的颤抖效果

我确定两个系统上的库(MoviePy、Gizeh、Cairocffi、cffi 等)版本是相同的。我也尝试了高 fps 或缩小测试,但没有奏效。

我不知道这可能是我这边的问题还是编码错误。

我试图找出导致此问题的原因。我在 gizeh.py 第 489 行(与cairo_text_extents相同,在 cairocffi 库,context.py,第 2003行)中发现函数ctx.text_extents(txt)的返回值在 Linux 上的每一帧都不同。在 Mac 上,该函数总是返回相同的值。但是,即使我固定了这些值,效果还是一样的。

import sys
import gizeh as gz
from moviepy.editor import *

def make_frame(t):
    surface = gz.Surface(360, 180, bg_color=(0, 0, 0))
    text = gz.text('ENLARGE', fontsize=40, fontfamily='Arial Unicode',
                   fill=(255,255,255), xy=(180, 90), fontweight='normal')
    text = text.scale(1+0.5*t, center=[180, 90])
    text.draw(surface)
    return surface.get_npimage()

child_clip = VideoClip(make_frame, duration=3)
child_clip.write_gif('Result.gif',fps=24)

我在开罗图书馆找到了这个问题。我写了一个简单的演示来创建一系列放大文本字符串的图像。我打印了函数 cairo_text_extents() 的返回值,它指示了字符串的范围。我在 Linux 和 MacOS 上运行相同的代码。MacOS 上的值保持不变。在 Linux 上,每个帧的值都不同。尝试找出原因。

#include "cairo.h"
#include <stdio.h>


int draw (const char* filename, float t)
{
    cairo_surface_t *ImageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,360,360);

    cairo_t *cr = cairo_create(ImageSurface);

    cairo_set_source_rgb (cr, 1., 1., 1.);
    cairo_paint (cr);

    cairo_matrix_t matrix;
    float scale = (1+0.5*t);
    float offset = -(0.5*t)/2*355;
    matrix.xx = scale;
    matrix.xy = 0;
    matrix.x0 = offset;
    matrix.yx = 0;
    matrix.yy = scale;
    matrix.y0 = offset;

    cairo_set_matrix(cr,&matrix);

    cairo_font_options_t *font_options = cairo_font_options_create();
    cairo_font_options_set_antialias(font_options,CAIRO_ANTIALIAS_NONE);
    cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_hint_metrics(font_options,CAIRO_HINT_METRICS_OFF);
    cairo_set_font_options(cr,font_options);

    cairo_select_font_face (cr, "Arial Unicode",
                CAIRO_FONT_SLANT_NORMAL,
                CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(cr,60);

    cairo_text_extents_t *text_extents = new cairo_text_extents_t;
    cairo_text_extents(cr,"ENLARGE",text_extents);
    printf("%f %f %f %f %f %f\n",text_extents->width,
                                text_extents->height,
                                text_extents->x_advance,
                                text_extents->y_advance,
                                text_extents->x_bearing,
                                text_extents->y_bearing);
    int x_shift = -text_extents->width/2-text_extents->x_bearing;
    int y_shift = -text_extents->height/2-text_extents->y_bearing;
    int x = 180 + x_shift;
    int y = 180 + y_shift;
    cairo_move_to (cr, x, y);
    cairo_text_path(cr,"ENLARGE");
    cairo_set_source_rgb(cr,0,0,0);
    cairo_fill(cr);

    cairo_surface_write_to_png(ImageSurface,filename);

    cairo_font_options_destroy(font_options);
    delete text_extents;
    cairo_destroy(cr);
    cairo_surface_destroy(ImageSurface);


    return 0;
}

int main()
{
    int i = 0;
    for(i = 0;i<10;i++)
    {
        char filename[256] = "";
        sprintf(filename,"result_%d.png",i);
        float t = 1.0/10 * i;

        draw((const char*)filename,t);
    }
    printf("hello world!!!\n");

    getchar();

    return 0;
}
4

1 回答 1

2

您必须在 Cairo(或 fontconfig)中禁用字体提示。我想这意味着设置CAIRO_HINT_METRICS_OFF和/或CAIRO_HINT_STYLE_NONE. 但是,我什至不知道 Gizeh 是什么,所以我不能告诉你如何禁用那里的提示。

于 2018-04-26T14:55:06.840 回答