[Ffmpeg-devel] [PATCH] drawtext.c: 09 fix draw_glyph

Gustavo Sverzut Barbieri barbieri
Wed Sep 13 13:37:16 CEST 2006


On 9/13/06, Michael Niedermayer <michaelni at gmx.at> wrote:
> Hi
>
> On Sun, Sep 10, 2006 at 04:29:56PM -0300, Gustavo Sverzut Barbieri wrote:
> > This fix the other major remaining bug with drawtext.c: drawing glyphs.
> >
> > The previous code was flawed due over-complicated outline detection,
> > this is much more simple: while visiting a glyph pixel, check if
> > neighbours are not pixels, in this case they're border and should be
> > draw as outline if this is the case.
> >
> > I believe this is the last patch to fix bugs and improve code. If
> > they're all ok then I'll post a "code cleanup" series of patches.
> [...]
> > @@ -317,65 +305,55 @@
> >  }
> >
> >
> > +static inline int bitmap_is_set(const FT_Bitmap *bitmap, const int x, const int y)
> > +{
> > +  const int idx = bitmap->pitch * y + x / 8;
> > +  const int is_pixel = bitmap->buffer[idx] & (0x80 >> (x % 8));
>
> /8 and %8 of signed integers is slow, you should use >>3 and &7

okay


> > +
> > +  return is_pixel;
> > +}
> > +
> > +static inline int bitmap_is_border(const FT_Bitmap *bitmap, const int x, const int y, const int dx, const int dy)
> > +{
> > +  if (x == 0 || x >= bitmap->width || y == 0 || y >= bitmap->rows)
> > +    return 1;
> > +  return !bitmap_is_set(bitmap, x + dx, y + dy);
> > +}
> >
> >
> >  static inline void draw_glyph(AVPicture *picture, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_fgcolor[3], unsigned char yuv_bgcolor[3], int outline)
> >  {
> >    int r, c;
> > -  int spixel, dpixel[3], in_glyph=0;
> >
> >    if (bitmap->pixel_mode == ft_pixel_mode_mono)
> >      {
> > -      in_glyph = 0;
> > -      for (r=0; (r < bitmap->rows) && (r+y < height); r++)
> > +      for (r=0; r < bitmap->rows; r++)
> >          {
> > -          for (c=0; (c < bitmap->width) && (c+x < width); c++)
> > +          for (c=0; c < bitmap->width; c++)
> >              {
> > -              /* pixel in the picture (destination) */
> > -              GET_PIXEL(picture, dpixel, (c+x), (y+r));
> > -
> > -              /* pixel in the glyph bitmap (source) */
> > -              spixel = bitmap->buffer[r*bitmap->pitch +c/8] & (0x80>>(c%8));
> > -
> > -              if (spixel)
> > -                COPY_3(dpixel, yuv_fgcolor);
> > -
> > -              if (outline)
> > +              if (bitmap_is_set(bitmap, c, r))
> >                  {
> > -                  /* border detection: */
> > -                  if ( (!in_glyph) && (spixel) )
> > -                    /* left border detected */
> > -                    {
> > -                      in_glyph = 1;
> > -                      /* draw left pixel border */
> > -                      if (c-1 >= 0)
> > -                        SET_PIXEL(picture, yuv_bgcolor, (c+x-1), (y+r));
> > -                    }
> > -                  else if ( (in_glyph) && (!spixel) )
> > -                    /* right border detected */
> > +                  if (outline)
> >                      {
> > -                      in_glyph = 0;
> > -                      /* 'draw' right pixel border */
> > -                      COPY_3(dpixel, yuv_bgcolor);
> > +                      if (bitmap_is_border(bitmap, c, r, -1, 0) &&
> > +                          c - 1 + x >= 0)
> > +                        SET_PIXEL(picture, yuv_bgcolor, c - 1 + x, r + y);
> > +
> > +                      if (bitmap_is_border(bitmap, c, r, +1, 0) &&
> > +                          c + 1 + x < width)
> > +                        SET_PIXEL(picture, yuv_bgcolor, c + 1 + x, r + y);
> > +
> > +                      if (bitmap_is_border(bitmap, c, r, 0, -1) &&
> > +                          r - 1 + y >= 0)
> > +                        SET_PIXEL(picture, yuv_bgcolor, c + x, r - 1 + y);
> > +
> > +                      if (bitmap_is_border(bitmap, c, r, 0, +1) &&
> > +                          r + 1 + y < height)
> > +                        SET_PIXEL(picture, yuv_bgcolor, c + x, r + 1 + y);
> >                      }
>
> the outline should be precalculated, instead of redoing the calculation for
> every pixel, also the code should be split into a inner optimized part and
> one for the areas close to the borders of the image to avoid the
> 0/width/height checks

I don't think pre-calculation will help here, since I'm already
visiting each pixel, then I must check if it's a border or not.

What I could do is something that ressembles the first version, where,
instead of looking at 4 neighbours, look at the next one (col + 1).
But this would add more conditionals, since I would have a state where
I'm at borders and still need to check if col + 1 < width.


> > -                  if (in_glyph)
> > -                    /* see if we have a top/bottom border */
> > -                    {
> > -                      /* top */
> > -                      if ( (r-1 >= 0) && (! bitmap->buffer[(r-1)*bitmap->pitch +c/8] & (0x80>>(c%8))) )
> > -                        /* we have a top border */
> > -                        SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r-1));
> > -
> > -                      /* bottom */
> > -                      if ( (r+1 < height) && (! bitmap->buffer[(r+1)*bitmap->pitch +c/8] & (0x80>>(c%8))) )
> > -                        /* we have a bottom border */
> > -                        SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r+1));
> > -
> > -                    }
> > +                  SET_PIXEL(picture, yuv_fgcolor, c + x, r + y);
>
> arent the chroma values totally wrong here? they are subsampled and just
> setting them to the color of the font if any of the 4 luma samples is part
> of the text isnt correct
> and actually the whole should be "antialiased" instead of the binary
> transparent vs. opaque

Yes, chroma values are not that right. But this was what the code did
and I keep it, since results are not that bad. I'll check how to
calculate the correct color based on other pixel value, any hints?

Thank you!

-- 
Gustavo Sverzut Barbieri
--------------------------------------
Jabber: barbieri at gmail.com
   MSN: barbieri at gmail.com
  ICQ#: 17249123
 Skype: gsbarbieri
Mobile: +55 (81) 9927 0010
 Phone:  +1 (347) 624 6296; 08122692 at sip.stanaphone.com
   GPG: 0xB640E1A2 @ wwwkeys.pgp.net




More information about the ffmpeg-devel mailing list