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