|
|
|
@ -696,49 +696,65 @@ static void RegionDraw( subpicture_region_t *p_region, ASS_Image *p_img ) |
|
|
|
const int i_width = p_region->fmt.i_width; |
|
|
|
const int i_height = p_region->fmt.i_height; |
|
|
|
|
|
|
|
memset( p->p_pixels, 0x00, p->i_pitch * p->i_lines ); |
|
|
|
memset( p->p_pixels, 0x00, p->i_pitch * p->i_visible_lines ); |
|
|
|
for( ; p_img != NULL; p_img = p_img->next ) |
|
|
|
{ |
|
|
|
if( p_img->dst_x < i_x || p_img->dst_x + p_img->w > i_x + i_width || |
|
|
|
p_img->dst_y < i_y || p_img->dst_y + p_img->h > i_y + i_height ) |
|
|
|
int i_dst_x = p_img->dst_x - i_x; |
|
|
|
int i_dst_y = p_img->dst_y - i_y; |
|
|
|
if( i_dst_x < 0 || i_dst_x + p_img->w > i_width || |
|
|
|
i_dst_y < 0 || i_dst_y + p_img->h > i_height ) |
|
|
|
continue; |
|
|
|
|
|
|
|
/* /!\ Bogus alpha channel is inverted */ |
|
|
|
const unsigned a = (~p_img->color )&0xff; |
|
|
|
if( a == 0 ) |
|
|
|
continue; |
|
|
|
|
|
|
|
const unsigned r = (p_img->color >> 24)&0xff; |
|
|
|
const unsigned g = (p_img->color >> 16)&0xff; |
|
|
|
const unsigned b = (p_img->color >> 8)&0xff; |
|
|
|
const unsigned a = (p_img->color )&0xff; |
|
|
|
int x, y; |
|
|
|
|
|
|
|
for( y = 0; y < p_img->h; y++ ) |
|
|
|
{ |
|
|
|
for( x = 0; x < p_img->w; x++ ) |
|
|
|
{ |
|
|
|
const unsigned alpha = p_img->bitmap[y*p_img->stride+x]; |
|
|
|
const unsigned an = (255 - a) * alpha / 255; |
|
|
|
const uint8_t *srcrow = p_img->bitmap; |
|
|
|
int i_pitch_src = p_img->stride; |
|
|
|
int i_pitch_dst = p->i_pitch; |
|
|
|
uint8_t *dstrow = &p->p_pixels[i_dst_y * i_pitch_dst + 4 * i_dst_x]; |
|
|
|
|
|
|
|
uint8_t *p_rgba = &p->p_pixels[(y+p_img->dst_y-i_y) * p->i_pitch + 4 * (x+p_img->dst_x-i_x)]; |
|
|
|
const unsigned ao = p_rgba[3]; |
|
|
|
for( int y = 0; y < p_img->h; y++ ) |
|
|
|
{ |
|
|
|
const uint8_t *src = srcrow; |
|
|
|
uint8_t *dst = dstrow; |
|
|
|
|
|
|
|
/* Native endianness, but RGBA ordering */ |
|
|
|
if( ao == 0 ) |
|
|
|
{ |
|
|
|
/* Optimized but the else{} will produce the same result */ |
|
|
|
p_rgba[0] = r; |
|
|
|
p_rgba[1] = g; |
|
|
|
p_rgba[2] = b; |
|
|
|
p_rgba[3] = an; |
|
|
|
} |
|
|
|
else |
|
|
|
for( int x = 0; x < p_img->w; x++ ) |
|
|
|
{ |
|
|
|
unsigned opacity = *src++; /* 1 Bpp channel */ |
|
|
|
if( opacity != 0 ) /* we need to blend only non transparent content */ |
|
|
|
{ |
|
|
|
p_rgba[3] = 255 - ( 255 - p_rgba[3] ) * ( 255 - an ) / 255; |
|
|
|
if( p_rgba[3] != 0 ) |
|
|
|
unsigned i_an = a * opacity / 255U; |
|
|
|
unsigned i_ao = dst[3]; |
|
|
|
if( i_ao == 0 ) |
|
|
|
{ |
|
|
|
dst[0] = r; |
|
|
|
dst[1] = g; |
|
|
|
dst[2] = b; |
|
|
|
dst[3] = i_an; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
p_rgba[0] = ( p_rgba[0] * ao * (255-an) / 255 + r * an ) / p_rgba[3]; |
|
|
|
p_rgba[1] = ( p_rgba[1] * ao * (255-an) / 255 + g * an ) / p_rgba[3]; |
|
|
|
p_rgba[2] = ( p_rgba[2] * ao * (255-an) / 255 + b * an ) / p_rgba[3]; |
|
|
|
unsigned i_ani = 255 - i_an; |
|
|
|
dst[3] = 255 - (255 - i_ao) * i_ani / 255; |
|
|
|
if( dst[3] != 0 ) |
|
|
|
{ |
|
|
|
unsigned i_aoni = i_ao * i_ani / 255; |
|
|
|
dst[0] = ( dst[0] * i_aoni + r * i_an ) / dst[3]; |
|
|
|
dst[1] = ( dst[1] * i_aoni + g * i_an ) / dst[3]; |
|
|
|
dst[2] = ( dst[2] * i_aoni + b * i_an ) / dst[3]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
dst += 4; |
|
|
|
} |
|
|
|
srcrow += i_pitch_src; |
|
|
|
dstrow += i_pitch_dst; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|