~ubuntu-branches/ubuntu/oneiric/avidemux/oneiric-proposed

« back to all changes in this revision

Viewing changes to plugins/ADM_videoFilters/Ass/ADM_libass/ass_bitmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2009-08-20 08:42:44 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20090820084244-bhh15xxd7x2vbcuh
Tags: 1:2.5.1+repack-0ubuntu1
* New upstream bugfix release (LP: #416066):
  - Re-enabled several video and audio encoders (regression introduced
    in 2.5.0)
  - Updated the FFmpeg libraries
  - More video encoders are now plugins
  - DV video encoder now supports more profiles
  - Fixed loading and saving issues with LAME, x264 and Xvid options
    (regression introduced in 2.5.0)
  - Fraps video decoding support
  - Lowpass-5 mode added to libavcodec deinterlacer filter plugin
  - Fixed formatting of parameters for various filters on 64-bit platforms
  - Updated libass
  - Fixed sizing of the bitrate control on various video encoder configure
    windows (regression introduced in 2.5.0)
  - Improved filter dialog for GTK+ interface
  - New navigation icons for GTK+ interface
  - Fixed the behaviour of several GTK+ open/save dialogs (regression
    introduced in 2.5.0)
  - asharp filter's Block Adaptive mode can now be disabled using the Qt
    interface
  - Re-enabled the colour chooser dialog using the Qt interface (regression
    introduced in 2.5.0)
  - GCC 4.4 support
  - Fixed issues with CMake build scripts when using multiple make jobs
    (regression introduced in 2.5.0)
* Remove debian/patches dir and drop all patches, now applied by upstream.
* Drop quilt support.
* debian/libavidemux0.install: Also install missing libraries.
* Move debian/install to debian/avidemux.install.
* debian/rules:
  - Build the internal ffmpeg version properly (thanks to Christian Marillat).
  - A bit of cleanup.
* debian/control:
  - Bump Standards-Version.
  - Update Homepage field.
  - Adjust libavidemux0 short description.
  - gtk -> GTK, qt -> QT.
  - Set myself as Maintainer.
* Repack the tarball to remove the debian/ dir provided by upstream:
  - Create debian/README.source.
  - Update debian/watch.
  - Add get-orig-source target to debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
2
 
// vim:ts=8:sw=8:noet:ai:
3
 
/*
4
 
  Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
5
 
 
6
 
  This program is free software; you can redistribute it and/or modify
7
 
  it under the terms of the GNU General Public License as published by
8
 
  the Free Software Foundation; either version 2 of the License, or
9
 
  (at your option) any later version.
10
 
 
11
 
  This program is distributed in the hope that it will be useful,
12
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
  GNU General Public License for more details.
15
 
 
16
 
  You should have received a copy of the GNU General Public License
17
 
  along with this program; if not, write to the Free Software
18
 
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
 
*/
20
 
 
21
 
#include <stdlib.h>
22
 
#include <string.h>
23
 
#include <math.h>
24
 
#include <assert.h>
25
 
#include <ft2build.h>
26
 
#include FT_GLYPH_H
27
 
 
28
 
#include "mputils.h"
29
 
#include "ass_bitmap.h"
30
 
 
31
 
struct ass_synth_priv_s {
32
 
        int tmp_w, tmp_h;
33
 
        unsigned short* tmp;
34
 
 
35
 
        int g_r;
36
 
        int g_w;
37
 
 
38
 
        unsigned *g;
39
 
        unsigned *gt2;
40
 
};
41
 
 
42
 
static const unsigned int maxcolor = 255;
43
 
static const unsigned base = 256;
44
 
static const double blur_radius = 1.5;
45
 
 
46
 
static int generate_tables(ass_synth_priv_t* priv, double radius)
47
 
{
48
 
        double A = log(1.0/base)/(radius*radius*2);
49
 
        int mx, i;
50
 
        double volume_diff, volume_factor = 0;
51
 
        unsigned volume;
52
 
 
53
 
        priv->g_r = ceil(radius);
54
 
        priv->g_w = 2*priv->g_r+1;
55
 
 
56
 
        if (priv->g_r) {
57
 
                priv->g = malloc(priv->g_w * sizeof(unsigned));
58
 
                priv->gt2 = malloc(256 * priv->g_w * sizeof(unsigned));
59
 
                if (priv->g==NULL || priv->gt2==NULL) {
60
 
                        return -1;
61
 
                }
62
 
        }
63
 
 
64
 
        if (priv->g_r) {
65
 
                // gaussian curve with volume = 256
66
 
                for (volume_diff=10000000; volume_diff>0.0000001; volume_diff*=0.5){
67
 
                        volume_factor+= volume_diff;
68
 
                        volume=0;
69
 
                        for (i = 0; i<priv->g_w; ++i) {
70
 
                                priv->g[i] = (unsigned)(exp(A * (i-priv->g_r)*(i-priv->g_r)) * volume_factor + .5);
71
 
                                volume+= priv->g[i];
72
 
                        }
73
 
                        if(volume>256) volume_factor-= volume_diff;
74
 
                }
75
 
                volume=0;
76
 
                for (i = 0; i<priv->g_w; ++i) {
77
 
                        priv->g[i] = (unsigned)(exp(A * (i-priv->g_r)*(i-priv->g_r)) * volume_factor + .5);
78
 
                        volume+= priv->g[i];
79
 
                }
80
 
 
81
 
                // gauss table:
82
 
                for(mx=0;mx<priv->g_w;mx++){
83
 
                        for(i=0;i<256;i++){
84
 
                                priv->gt2[mx+i*priv->g_w] = i*priv->g[mx];
85
 
                        }
86
 
                }
87
 
        }
88
 
 
89
 
        return 0;
90
 
}
91
 
 
92
 
static void resize_tmp(ass_synth_priv_t* priv, int w, int h)
93
 
{
94
 
        if (priv->tmp_w >= w && priv->tmp_h >= h)
95
 
                return;
96
 
        if (priv->tmp_w == 0)
97
 
                priv->tmp_w = 64;
98
 
        if (priv->tmp_h == 0)
99
 
                priv->tmp_h = 64;
100
 
        while (priv->tmp_w < w) priv->tmp_w *= 2;
101
 
        while (priv->tmp_h < h) priv->tmp_h *= 2;
102
 
        if (priv->tmp)
103
 
                free(priv->tmp);
104
 
        priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short));
105
 
}
106
 
 
107
 
ass_synth_priv_t* ass_synth_init(void)
108
 
{
109
 
        ass_synth_priv_t* priv = calloc(1, sizeof(ass_synth_priv_t));
110
 
        generate_tables(priv, blur_radius);
111
 
        return priv;
112
 
}
113
 
 
114
 
void ass_synth_done(ass_synth_priv_t* priv)
115
 
{
116
 
        if (priv->tmp)
117
 
                free(priv->tmp);
118
 
        if (priv->g)
119
 
                free(priv->g);
120
 
        if (priv->gt2)
121
 
                free(priv->gt2);
122
 
        free(priv);
123
 
}
124
 
 
125
 
static bitmap_t* alloc_bitmap(int w, int h)
126
 
{
127
 
        bitmap_t* bm;
128
 
        bm = calloc(1, sizeof(bitmap_t));
129
 
        bm->buffer = malloc(w*h);
130
 
        bm->w = w;
131
 
        bm->h = h;
132
 
        bm->left = bm->top = 0;
133
 
        return bm;
134
 
}
135
 
 
136
 
void ass_free_bitmap(bitmap_t* bm)
137
 
{
138
 
        if (bm) {
139
 
                if (bm->buffer) free(bm->buffer);
140
 
                free(bm);
141
 
        }
142
 
}
143
 
 
144
 
static bitmap_t* copy_bitmap(const bitmap_t* src)
145
 
{
146
 
        bitmap_t* dst = alloc_bitmap(src->w, src->h);
147
 
        dst->left = src->left;
148
 
        dst->top = src->top;
149
 
        memcpy(dst->buffer, src->buffer, src->w * src->h);
150
 
        return dst;
151
 
}
152
 
 
153
 
static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
154
 
{
155
 
        FT_BitmapGlyph bg;
156
 
        FT_Bitmap* bit;
157
 
        bitmap_t* bm;
158
 
        int w, h;
159
 
        unsigned char* src;
160
 
        unsigned char* dst;
161
 
        int i;
162
 
        int error;
163
 
 
164
 
        error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 0);
165
 
        if (error) {
166
 
                mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FT_Glyph_To_BitmapError, error);
167
 
                return 0;
168
 
        }
169
 
 
170
 
        bg = (FT_BitmapGlyph)glyph;
171
 
        bit = &(bg->bitmap);
172
 
        if (bit->pixel_mode != FT_PIXEL_MODE_GRAY) {
173
 
                mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UnsupportedPixelMode, (int)(bit->pixel_mode));
174
 
                FT_Done_Glyph(glyph);
175
 
                return 0;
176
 
        }
177
 
 
178
 
        w = bit->width;
179
 
        h = bit->rows;
180
 
        bm = alloc_bitmap(w + 2*bord, h + 2*bord);
181
 
        memset(bm->buffer, 0, bm->w * bm->h);
182
 
        bm->left = bg->left - bord;
183
 
        bm->top = - bg->top - bord;
184
 
 
185
 
        src = bit->buffer;
186
 
        dst = bm->buffer + bord + bm->w * bord;
187
 
        for (i = 0; i < h; ++i) {
188
 
                memcpy(dst, src, w);
189
 
                src += bit->pitch;
190
 
                dst += bm->w;
191
 
        }
192
 
 
193
 
        return bm;
194
 
}
195
 
 
196
 
/**
197
 
 * \brief fix outline bitmap and generate shadow bitmap
198
 
 * Two things are done here:
199
 
 * 1. Glyph bitmap is subtracted from outline bitmap. This way looks much better in some cases.
200
 
 * 2. Shadow bitmap is created as a sum of glyph and outline bitmaps.
201
 
 */
202
 
static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o)
203
 
{
204
 
        int x, y;
205
 
        const int l = bm_o->left > bm_g->left ? bm_o->left : bm_g->left;
206
 
        const int t = bm_o->top > bm_g->top ? bm_o->top : bm_g->top;
207
 
        const int r = bm_o->left + bm_o->w < bm_g->left + bm_g->w ? bm_o->left + bm_o->w : bm_g->left + bm_g->w;
208
 
        const int b = bm_o->top + bm_o->h < bm_g->top + bm_g->h ? bm_o->top + bm_o->h : bm_g->top + bm_g->h;
209
 
 
210
 
        bitmap_t* bm_s = copy_bitmap(bm_o);
211
 
 
212
 
        unsigned char* g = bm_g->buffer + (t - bm_g->top) * bm_g->w + (l - bm_g->left);
213
 
        unsigned char* o = bm_o->buffer + (t - bm_o->top) * bm_o->w + (l - bm_o->left);
214
 
        unsigned char* s = bm_s->buffer + (t - bm_s->top) * bm_s->w + (l - bm_s->left);
215
 
        
216
 
        for (y = 0; y < b - t; ++y) {
217
 
                for (x = 0; x < r - l; ++x) {
218
 
                        unsigned char c_g, c_o;
219
 
                        c_g = g[x];
220
 
                        c_o = o[x];
221
 
                        o[x] = (c_o > c_g) ? c_o : 0;
222
 
                        s[x] = (c_o < 0xFF - c_g) ? c_o + c_g : 0xFF;
223
 
                }
224
 
                g += bm_g->w;
225
 
                o += bm_o->w;
226
 
                s += bm_s->w;
227
 
        }
228
 
 
229
 
        assert(bm_s);
230
 
        return bm_s;
231
 
}
232
 
 
233
 
int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph,
234
 
                bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be)
235
 
{
236
 
        const int bord = be ? ceil(blur_radius) : 0;
237
 
 
238
 
        assert(bm_g && bm_o && bm_s);
239
 
 
240
 
        *bm_g = *bm_o = *bm_s = 0;
241
 
 
242
 
        if (glyph)
243
 
                *bm_g = glyph_to_bitmap_internal(glyph, bord);
244
 
        if (!*bm_g)
245
 
                return 1;
246
 
 
247
 
        if (outline_glyph) {
248
 
                *bm_o = glyph_to_bitmap_internal(outline_glyph, bord);
249
 
                if (!*bm_o) {
250
 
                        ass_free_bitmap(*bm_g);
251
 
                        return 1;
252
 
                }
253
 
        }
254
 
        if (*bm_o)
255
 
                resize_tmp(priv, (*bm_o)->w, (*bm_o)->h);
256
 
        resize_tmp(priv, (*bm_g)->w, (*bm_g)->h);
257
 
        
258
 
        if (be) {
259
 
                blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
260
 
                if (*bm_o)
261
 
                        blur((*bm_o)->buffer, priv->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
262
 
        }
263
 
 
264
 
        if (*bm_o)
265
 
                *bm_s = fix_outline_and_shadow(*bm_g, *bm_o);
266
 
        else
267
 
                *bm_s = copy_bitmap(*bm_g);
268
 
 
269
 
        assert(bm_s);
270
 
        return 0;
271
 
}
272