From c13cb222435ff61533a26efcd46c6246ea541dc1 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Sun, 26 Jun 2011 05:44:52 +0200 Subject: bitmap: add stride Add stride support to the basic bitmap type used for low-level rasterization. --- libass/ass_bitmap.c | 80 +++++++++++++++++++++++++++++------------------------ libass/ass_bitmap.h | 1 + libass/ass_render.c | 16 +++++------ 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 949126a..5a2dc80 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -135,10 +135,12 @@ void ass_synth_done(ASS_SynthPriv *priv) static Bitmap *alloc_bitmap(int w, int h) { Bitmap *bm; + unsigned s = w; // XXX: alignment bm = malloc(sizeof(Bitmap)); - bm->buffer = calloc(w, h); + bm->buffer = calloc(s, h); bm->w = w; bm->h = h; + bm->stride = s; bm->left = bm->top = 0; return bm; } @@ -155,7 +157,7 @@ static Bitmap *copy_bitmap(const Bitmap *src) Bitmap *dst = alloc_bitmap(src->w, src->h); dst->left = src->left; dst->top = src->top; - memcpy(dst->buffer, src->buffer, src->w * src->h); + memcpy(dst->buffer, src->buffer, src->stride * src->h); return dst; } @@ -194,8 +196,8 @@ Bitmap *outline_to_bitmap(ASS_Library *library, FT_Library ftlib, bm->top = -bbox.yMax - bord; bitmap.width = w; bitmap.rows = h; - bitmap.pitch = bm->w; - bitmap.buffer = bm->buffer + bord + bm->w * bord; + bitmap.pitch = bm->stride; + bitmap.buffer = bm->buffer + bord + bm->stride * bord; bitmap.num_grays = 256; bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; @@ -223,16 +225,16 @@ static void fix_outline(Bitmap *bm_g, Bitmap *bm_o) const int l = bm_o->left > bm_g->left ? bm_o->left : bm_g->left; const int t = bm_o->top > bm_g->top ? bm_o->top : bm_g->top; 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; + bm_o->left + bm_o->stride < + bm_g->left + bm_g->stride ? bm_o->left + bm_o->stride : bm_g->left + bm_g->stride; 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; unsigned char *g = - bm_g->buffer + (t - bm_g->top) * bm_g->w + (l - bm_g->left); + bm_g->buffer + (t - bm_g->top) * bm_g->stride + (l - bm_g->left); unsigned char *o = - bm_o->buffer + (t - bm_o->top) * bm_o->w + (l - bm_o->left); + bm_o->buffer + (t - bm_o->top) * bm_o->stride + (l - bm_o->left); for (y = 0; y < b - t; ++y) { for (x = 0; x < r - l; ++x) { @@ -241,8 +243,8 @@ static void fix_outline(Bitmap *bm_g, Bitmap *bm_o) c_o = o[x]; o[x] = (c_o > c_g) ? c_o - (c_g / 2) : 0; } - g += bm_g->w; - o += bm_o->w; + g += bm_g->stride; + o += bm_o->stride; } } @@ -250,27 +252,30 @@ static void fix_outline(Bitmap *bm_g, Bitmap *bm_o) * \brief Shift a bitmap by the fraction of a pixel in x and y direction * expressed in 26.6 fixed point */ -static void shift_bitmap(unsigned char *buf, int w, int h, int shift_x, - int shift_y) +static void shift_bitmap(Bitmap *bm, int shift_x, int shift_y) { int x, y, b; + int w = bm->w; + int h = bm->h; + int s = bm->stride; + unsigned char *buf = bm->buffer; // Shift in x direction if (shift_x > 0) { for (y = 0; y < h; y++) { for (x = w - 1; x > 0; x--) { - b = (buf[x + y * w - 1] * shift_x) >> 6; - buf[x + y * w - 1] -= b; - buf[x + y * w] += b; + b = (buf[x + y * s - 1] * shift_x) >> 6; + buf[x + y * s - 1] -= b; + buf[x + y * s] += b; } } } else if (shift_x < 0) { shift_x = -shift_x; for (y = 0; y < h; y++) { for (x = 0; x < w - 1; x++) { - b = (buf[x + y * w + 1] * shift_x) >> 6; - buf[x + y * w + 1] -= b; - buf[x + y * w] += b; + b = (buf[x + y * s + 1] * shift_x) >> 6; + buf[x + y * s + 1] -= b; + buf[x + y * s] += b; } } } @@ -279,18 +284,18 @@ static void shift_bitmap(unsigned char *buf, int w, int h, int shift_x, if (shift_y > 0) { for (x = 0; x < w; x++) { for (y = h - 1; y > 0; y--) { - b = (buf[x + (y - 1) * w] * shift_y) >> 6; - buf[x + (y - 1) * w] -= b; - buf[x + y * w] += b; + b = (buf[x + (y - 1) * s] * shift_y) >> 6; + buf[x + (y - 1) * s] -= b; + buf[x + y * s] += b; } } } else if (shift_y < 0) { shift_y = -shift_y; for (x = 0; x < w; x++) { for (y = 0; y < h - 1; y++) { - b = (buf[x + (y + 1) * w] * shift_y) >> 6; - buf[x + (y + 1) * w] -= b; - buf[x + y * w] += b; + b = (buf[x + (y + 1) * s] * shift_y) >> 6; + buf[x + (y + 1) * s] -= b; + buf[x + y * s] += b; } } } @@ -421,16 +426,20 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, * \brief Blur with [[1,2,1]. [2,4,2], [1,2,1]] kernel * This blur is the same as the one employed by vsfilter. */ -static void be_blur(unsigned char *buf, int w, int h) +static void be_blur(Bitmap *bm) { + int w = bm->w; + int h = bm->h; + int s = bm->stride; + unsigned char *buf = bm->buffer; unsigned int x, y; unsigned int old_sum, new_sum; for (y = 0; y < h; y++) { - old_sum = 2 * buf[y * w]; + old_sum = 2 * buf[y * s]; for (x = 0; x < w - 1; x++) { - new_sum = buf[y * w + x] + buf[y * w + x + 1]; - buf[y * w + x] = (old_sum + new_sum) >> 2; + new_sum = buf[y * s + x] + buf[y * s + x + 1]; + buf[y * s + x] = (old_sum + new_sum) >> 2; old_sum = new_sum; } } @@ -438,8 +447,8 @@ static void be_blur(unsigned char *buf, int w, int h) for (x = 0; x < w; x++) { old_sum = 2 * buf[x]; for (y = 0; y < h - 1; y++) { - new_sum = buf[y * w + x] + buf[(y + 1) * w + x]; - buf[y * w + x] = (old_sum + new_sum) >> 2; + new_sum = buf[y * s + x] + buf[(y + 1) * s + x]; + buf[y * s + x] = (old_sum + new_sum) >> 2; old_sum = new_sum; } } @@ -477,9 +486,9 @@ int outline_to_bitmap3(ASS_Library *library, ASS_SynthPriv *priv_blur, // Apply box blur (multiple passes, if requested) while (be--) { if (*bm_o) - be_blur((*bm_o)->buffer, (*bm_o)->w, (*bm_o)->h); + be_blur(*bm_o); else - be_blur((*bm_g)->buffer, (*bm_g)->w, (*bm_g)->h); + be_blur(*bm_o); } // Apply gaussian blur @@ -491,12 +500,12 @@ int outline_to_bitmap3(ASS_Library *library, ASS_SynthPriv *priv_blur, generate_tables(priv_blur, blur_radius); if (*bm_o) ass_gauss_blur((*bm_o)->buffer, priv_blur->tmp, - (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, + (*bm_o)->w, (*bm_o)->h, (*bm_o)->stride, (int *) priv_blur->gt2, priv_blur->g_r, priv_blur->g_w); else ass_gauss_blur((*bm_g)->buffer, priv_blur->tmp, - (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, + (*bm_g)->w, (*bm_g)->h, (*bm_g)->stride, (int *) priv_blur->gt2, priv_blur->g_r, priv_blur->g_w); } @@ -512,8 +521,7 @@ int outline_to_bitmap3(ASS_Library *library, ASS_SynthPriv *priv_blur, assert(bm_s); - shift_bitmap((*bm_s)->buffer, (*bm_s)->w,(*bm_s)->h, - shadow_offset.x, shadow_offset.y); + shift_bitmap(*bm_s, shadow_offset.x, shadow_offset.y); return 0; } diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h index d21ea4e..2a46aec 100644 --- a/libass/ass_bitmap.h +++ b/libass/ass_bitmap.h @@ -32,6 +32,7 @@ void ass_synth_done(ASS_SynthPriv *priv); typedef struct { int left, top; int w, h; // width, height + int stride; unsigned char *buffer; // w x h buffer } Bitmap; diff --git a/libass/ass_render.c b/libass/ass_render.c index 021bfc4..b036bf2 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -296,18 +296,18 @@ static ASS_Image **render_glyph_i(ASS_Renderer *render_priv, // split up into left and right for karaoke, if needed if (lbrk > r[j].x0) { if (lbrk > r[j].x1) lbrk = r[j].x1; - img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->w + r[j].x0, + img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->stride + r[j].x0, lbrk - r[j].x0, r[j].y1 - r[j].y0, - bm->w, dst_x + r[j].x0, dst_y + r[j].y0, color); + bm->stride, dst_x + r[j].x0, dst_y + r[j].y0, color); if (!img) break; *tail = img; tail = &img->next; } if (lbrk < r[j].x1) { if (lbrk < r[j].x0) lbrk = r[j].x0; - img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->w + lbrk, + img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->stride + lbrk, r[j].x1 - lbrk, r[j].y1 - r[j].y0, - bm->w, dst_x + lbrk, dst_y + r[j].y0, color2); + bm->stride, dst_x + lbrk, dst_y + r[j].y0, color2); if (!img) break; *tail = img; tail = &img->next; @@ -387,8 +387,8 @@ render_glyph(ASS_Renderer *render_priv, Bitmap *bm, int dst_x, int dst_y, if (brk > b_x0) { // draw left part if (brk > b_x1) brk = b_x1; - img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + b_x0, - brk - b_x0, b_y1 - b_y0, bm->w, + img = my_draw_bitmap(bm->buffer + bm->stride * b_y0 + b_x0, + brk - b_x0, b_y1 - b_y0, bm->stride, dst_x + b_x0, dst_y + b_y0, color); if (!img) return tail; *tail = img; @@ -397,8 +397,8 @@ render_glyph(ASS_Renderer *render_priv, Bitmap *bm, int dst_x, int dst_y, if (brk < b_x1) { // draw right part if (brk < b_x0) brk = b_x0; - img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + brk, - b_x1 - brk, b_y1 - b_y0, bm->w, + img = my_draw_bitmap(bm->buffer + bm->stride * b_y0 + brk, + b_x1 - brk, b_y1 - b_y0, bm->stride, dst_x + brk, dst_y + b_y0, color2); if (!img) return tail; *tail = img; -- cgit v1.2.3