[FFmpeg-devel] [PATCH] X-Face image encoder and decoder

Stefano Sabatini stefasab at gmail.com
Sat Oct 13 01:44:43 CEST 2012


On date Wednesday 2012-10-10 01:43:01 +0200, Michael Niedermayer encoded:
> Hi
> 
> On Tue, Oct 09, 2012 at 05:10:05PM +0200, Stefano Sabatini wrote:
> > On date Thursday 2012-07-26 23:54:50 +0200, Stefano Sabatini encoded:
> > > Hi,
> > > 
> > > this is a yet unready version of an X-Face encoder and decoder I did
> > > for fun. I tried to contact the libcompface author to see if he's OK
> > > with the licensing port.
> > 
> > James Ashton (in CC:) replied telling that he's OK with LGPL
> > relicensing.
> > 
> > > I post it here for backup purposes, and to see if there is some
> > > interest for it (but I warn again that it is not yet ready for
> > > inclusion, so don't review yet).
> > > 
> > > Todo:
> > > - add documentation
> > > - add missing buffer checks
> > > 
> > 
> > > I also wonder if we could adapt our big integer implementation
> > > (libavutil/integer.h) for it, and if someone can recommend fancy
> > > options for creating a 48x48x1 image with ffmpeg in the best possible
> > > way (dithering options, etc.).
> > 
> > Updated against the integer patch I posted recently.
> > -- 
> > FFmpeg = Fabulous and Fundamental Multimedia Philosophical Elastic Gem
> 
> [...]
> >  libavcodec/Makefile     |    2 +
> >  libavcodec/allcodecs.c  |    1 +
> >  libavcodec/avcodec.h    |    1 +
> >  libavcodec/codec_desc.c |    7 +
> >  libavcodec/xface.c      |  591 +++++++++++++++++++++++++++++++++++++++++++++++
> >  libavcodec/xface.h      |   56 +++++
> >  libavcodec/xfacedec.c   |  225 ++++++++++++++++++
> >  libavcodec/xfaceenc.c   |  244 +++++++++++++++++++
> >  libavformat/img2.c      |    1 +
> >  9 files changed, 1128 insertions(+), 0 deletions(-)
> >  create mode 100644 libavcodec/xface.c
> >  create mode 100644 libavcodec/xface.h
> >  create mode 100644 libavcodec/xfacedec.c
> >  create mode 100644 libavcodec/xfaceenc.c
> 
> the code looks fine, i could point to some possible tricks to
> make it faster but its kind of silly for 48x48 images on modern hw
> so some of the comments below should not be taken serious :)
> 
> 
> [...]
> > +static const uint8_t g_00[1<<12] = {
> > +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> > +    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
> > +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> > +    1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
> 
> these tables could be stored more compactly by using bits instead of
> bytes

Done (I'm attaching conversion program+patch for archival reasons,
will squash them together when committing / at the next iteration).
  
> [...]
> > +void ff_xface_generate_face(uint8_t *dst, uint8_t * const src)
> > +{
> > +    int m, l, k, j, i, h;
> > +
> > +    for (j = 0; j < XFACE_HEIGHT; j++) {
> > +        for (i = 0; i < XFACE_WIDTH; i++) {
> > +            h = i + j * XFACE_WIDTH;
> > +            k = 0;
> > +
> > +            /*
> > +               Compute k, encoding the bits *before* the current one, contained in the
> > +               image buffer. That is, given the grid:
> > +
> > +                l      i
> > +                |      |
> > +                v      v
> > +               +--+--+--+--+--+
> > +          m -> | 1| 2| 3| 4| 5|
> > +               +--+--+--+--+--+
> > +               | 6| 7| 8| 9|10|
> > +               +--+--+--+--+--+
> > +          j -> |11|12| *|  |  |
> > +               +--+--+--+--+--+
> > +
> > +               the value k for the pixel marked as "*" will contain the bit encoding of
> > +               the values in the matrix marked from "1" to "12". In case the pixel is
> > +               near the border of the grid, the number of values contained within the
> > +               grid will be lesser than 12.
> > +             */
> > +
> > +            for (l = i - 2; l <= i + 2; l++) {
> > +                for (m = j - 2; m <= j; m++) {
> > +                    if (l >= i && m == j)
> > +                        continue;
> > +                    if (l > 0 && l <= XFACE_WIDTH && m > 0)
> 
> > +                        k = *(src + l + m * XFACE_WIDTH) ? k * 2 + 1 : k * 2;
> 
> k = 2*k + src[src + l + m * XFACE_WIDTH];

Changed.

> also instead of reading 12 values you can reuse the k from the
> left pixel, shift it by 1 bit and update just 3 values, but given the
> small size its not worth the work

Uhm yes, but both for lazyness and for staying close to the original
source I'm keeping it the current way.

> [...]
> > +
> > +/* define the face size - 48x48x1 */
> > +#define XFACE_WIDTH  48
> > +#define XFACE_HEIGHT 48
> > +#define XFACE_PIXELS (XFACE_WIDTH * XFACE_HEIGHT)
> > +
> > +/* compressed output uses the full range of printable characters.
> > + * in ASCII these are in a contiguous block so we just need to know
> > + * the first and last.  The total number of printables is needed too */
> > +#define XFACE_FIRSTPRINT '!'
> > +#define XFACE_LASTPRINT '~'
> > +#define XFACE_NUMPRINTS (XFACE_LASTPRINT - XFACE_FIRSTPRINT + 1)
> > +
> > +/* Each face is encoded using 9 octrees of 16x16 each.  Each level of the
> > + * trees has varying probabilities of being white, grey or black.
> > + * The table below is based on sampling many faces */
> > +enum { BLACK = 0, GREY, WHITE };
> 
> some of these comments could/should be made to /** doxgen comments
> 
> also i suspect that several pop_integer() calls could be merged using
> a large LUT to decode several symbols at a time and then adjust b
> for all of them at once. Again not worth for 48x48 images
> 
> Thanks to james and stefano for writing and porting this codec !

Patch updated.

Note: what's the best way to check encoder+decoder in FATE? Also
what's the recommended way to add an xface test? Would this require to
add a sample to SAMPLES, or should we rely on the encoder?.
-- 
FFmpeg = Furious and Fast Mind-dumbing Portable Esoteric Gnome
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-lavc-add-xface-image-decoder-and-encoder.patch
Type: text/x-diff
Size: 50726 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121013/6658ac7e/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-lavc-xface-write-program-to-generate-compact-guess-t.patch
Type: text/x-diff
Size: 2680 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121013/6658ac7e/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-lavc-xface-make-guess-tables-more-compact.patch
Type: text/x-diff
Size: 28347 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121013/6658ac7e/attachment-0002.bin>


More information about the ffmpeg-devel mailing list