Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text Zooming Effect Trembling

I created a text zooming animation with MoviePy and Gizeh. However the results turned out different when the code is run on different OS. The following two gifs are generated by the same python code. The effect looks pretty good on MacOS, but poor on Linux.

pretty good on MacOS

pretty good on MacOS

effect trembling on Linux

effect trembling on Linux

I'm sure that the libraries(MoviePy, Gizeh, Cairocffi, cffi, etc.) versions are the same on both systems. I also tried high fps or downsize the test but it didn't work.

I don't know if this may be an issue or bad coding from my side.

I tried to find out what caused this issue. I found the return values of the function ctx.text_extents(txt) in gizeh.py Line 489 ( same as cairo_text_extents, in cairocffi library, context.py, Line 2003) varies every frame on Linux. And on Mac the function always return the same values. However, even if I fixed the values, the effect remained the same.

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)

I have locate this problem in Cairo library. I wrote a simple demo to create a sequence of images enlarging the text string. And I printed the return values of the function cairo_text_extents() which indicated the extents of the string. I run the same code on Linux and MacOS. The values stayed the same on MacOS. While on Linux, the values varied every frame. Tring to figure out why.

#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;
}
like image 561
陈羽飞 Avatar asked Nov 30 '25 14:11

陈羽飞


1 Answers

You have to disable font hinting in Cairo (or fontconfig). I guess this means to set CAIRO_HINT_METRICS_OFF and/or CAIRO_HINT_STYLE_NONE. However, I do not even know what Gizeh is and so I cannot tell you how to disable hinting there.

like image 182
Uli Schlachter Avatar answered Dec 02 '25 02:12

Uli Schlachter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!