libimg: Improve support of transparent PNG images.

* Support grayscale images with alpha channel.
* Support rgb images with transparent color.
* Process 'tRNS' chunk (simple transparency).

Transparent png images were already supported for color type 6, which
is RGBA. Now indexed images (color type 3) can also have transparency
via 'tRNS' chunk data.

git-svn-id: svn://kolibrios.org@8449 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Ivan Baravy 2020-12-18 22:08:51 +00:00
parent 045e0dbdd2
commit 459cb3ec5b
2 changed files with 130 additions and 38 deletions

View File

@ -633,6 +633,22 @@ proc img._.convert.bpp8a_to_bpp24 _src, _dst
endp endp
proc img._.convert.bpp8a_to_bpp32 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
lodsw
shl eax, 8
mov al, ah
shl eax, 8
mov al, ah
stosd
dec ecx
jnz @b
ret
endp
img.convert.bpp8i.table: img.convert.bpp8i.table:
dd Image.bpp24, img._.convert.bpp8i_to_bpp24 dd Image.bpp24, img._.convert.bpp8i_to_bpp24
dd Image.bpp32, img._.convert.bpp8i_to_bpp32 dd Image.bpp32, img._.convert.bpp8i_to_bpp32
@ -665,6 +681,7 @@ img.convert.bpp4i.table:
dd 0 dd 0
img.convert.bpp8a.table: img.convert.bpp8a.table:
dd Image.bpp24, img._.convert.bpp8a_to_bpp24 dd Image.bpp24, img._.convert.bpp8a_to_bpp24
dd Image.bpp32, img._.convert.bpp8a_to_bpp32
dd 0 dd 0
img.convert.table: img.convert.table:

View File

@ -56,12 +56,13 @@ img.decode.png:
xor eax, eax ; .image = 0 xor eax, eax ; .image = 0
pushad pushad
mov ebp, esp mov ebp, esp
.localsize = 29*4 .localsize = 30*4
virtual at ebp - .localsize virtual at ebp - .localsize
.width dd ? .width dd ?
.height dd ? .height dd ?
.bit_depth dd ? .bit_depth dd ?
.color_type dd ? .color_type dd ?
.transparent_color dd ?
.bytes_per_pixel dd ? .bytes_per_pixel dd ?
.scanline_len dd ? .scanline_len dd ?
.bits_per_pixel dd ? .bits_per_pixel dd ?
@ -158,6 +159,8 @@ end virtual
jz .iend jz .iend
cmp eax, 'PLTE' cmp eax, 'PLTE'
jz .palette jz .palette
cmp eax, 'tRNS'
jz .transparency
; unrecognized chunk, ignore ; unrecognized chunk, ignore
lea esi, [esi+ecx+4] lea esi, [esi+ecx+4]
pop ecx pop ecx
@ -233,14 +236,17 @@ end virtual
add eax, 7 add eax, 7
shr eax, 3 shr eax, 3
mov [.bytes_per_pixel], eax mov [.bytes_per_pixel], eax
mov [.transparent_color], 0
; allocate image ; allocate image
push Image.bpp24 movi eax, Image.bpp32
pop eax
cmp [.color_type], 2 cmp [.color_type], 2
jz @f jz @f
mov al, Image.bpp32 mov al, Image.bpp32
cmp [.color_type], 6 cmp [.color_type], 6
jz @f jz @f
mov al, Image.bpp8a
cmp [.color_type], 4
jz @f
mov al, Image.bpp8i mov al, Image.bpp8i
@@: @@:
stdcall img.create, [.width], [.height], eax stdcall img.create, [.width], [.height], eax
@ -288,11 +294,73 @@ end virtual
lodsd lodsd
dec esi dec esi
bswap eax bswap eax
shr eax, 8 mov al, 0xff
ror eax, 8
stosd stosd
jmp .next_chunk jmp .next_chunk
; convert 16 bit sample to 8 bit sample
macro convert_16_to_8
{
local .l1,.l2
xor ah, 0x80
js .l1
cmp al, ah
adc al, 0
jmp .l2
.l1:
cmp ah, al
sbb al, 0
.l2:
}
; tRNS chunk
.transparency:
mov eax, [.image]
test eax, eax
jz .invalid_chunk
cmp [.color_type], 2 ; rgb
jz .transparency_rgb
cmp [.color_type], 3 ; indexed
jz .transparency_indexed
add esi, ecx
jmp .next_chunk
.transparency_rgb:
cmp [.bit_depth], 16
jz .transparency_rgb16
lodsw
shl eax, 8
lodsw
shl eax, 8
lodsw
mov al, 0xff
ror eax, 8
mov [.transparent_color], eax
jmp .next_chunk
.transparency_rgb16:
lodsw
convert_16_to_8
shl ax, 8
shl eax, 8
lodsw
convert_16_to_8
shl ax, 8
shl eax, 8
lodsw
convert_16_to_8
shl ax, 8
mov al, 0xff
ror eax, 8
mov [.transparent_color], eax
jmp .next_chunk
.transparency_indexed:
mov edi, [eax + Image.Palette]
@@:
add edi, 3
movsb
loop @b
jmp .next_chunk
.idat: .idat:
jecxz .next_chunk test ecx, ecx
jz .next_chunk
cmp [.idat_read], 0 cmp [.idat_read], 0
jnz @f jnz @f
lodsb lodsb
@ -654,22 +722,6 @@ macro init_block
init_block init_block
lea eax, [edi+eax*4] lea eax, [edi+eax*4]
push eax push eax
; convert 16 bit sample to 8 bit sample
macro convert_16_to_8
{
local .l1,.l2
xor ah, 0x80
js .l1
cmp al, ah
adc al, 0
jmp .l2
.l1:
cmp ah, al
sbb al, 0
.l2:
}
.rgb_alpha2_16bit.innloop1: .rgb_alpha2_16bit.innloop1:
push edi push edi
mov ecx, ebx mov ecx, ebx
@ -872,20 +924,21 @@ local .l1
mov [.i], ecx mov [.i], ecx
.rgb2.extloop: .rgb2.extloop:
init_block init_block
lea eax, [eax*3] lea eax, [edi+eax*4]
add eax, edi
push eax push eax
.rgb2.innloop1: .rgb2.innloop1:
push edi push edi
mov ecx, ebx mov ecx, ebx
.rgb2.innloop2: .rgb2.innloop2:
mov al, [esi+2] mov eax, [esi]
mov [edi], al bswap eax
mov al, [esi+1] mov al, 0xff
mov [edi+1], al ror eax, 8
mov al, [esi] cmp eax, [.transparent_color]
mov [edi+2], al jnz @f
add edi, 3 and eax, 0x00ffffff
@@:
stosd
dec ecx dec ecx
jnz .rgb2.innloop2 jnz .rgb2.innloop2
pop edi pop edi
@ -947,7 +1000,6 @@ local .l1
ja .rgb2_16bit ja .rgb2_16bit
jmp .convert_done jmp .convert_done
.grayscale_alpha2: .grayscale_alpha2:
call .create_grayscale_palette
cmp [.bit_depth], 16 cmp [.bit_depth], 16
jz .grayscale_alpha2_16bit jz .grayscale_alpha2_16bit
.grayscale_alpha2.next: .grayscale_alpha2.next:
@ -961,11 +1013,29 @@ local .l1
mov [.i], ecx mov [.i], ecx
.grayscale_alpha2.extloop: .grayscale_alpha2.extloop:
init_block init_block
add eax, eax
add eax, edi add eax, edi
push eax push eax
mov al, [esi] lodsw
add esi, 2 macro block_word_innerloop extloop
block_byte_innerloop .grayscale_alpha2.extloop {
local .l1
.l1:
mov ecx, ebx
rep stosw
sub edi, ebx
add edi, [.row_distance]
dec edx
jnz .l1
pop edi ebx
mov eax, [.col_increment]
sub [.i], eax
ja extloop
add edi, [.col_distance]
mov eax, [.row_increment]
sub [.j], eax
}
block_word_innerloop .grayscale_alpha2.extloop
ja .grayscale_alpha2.next ja .grayscale_alpha2.next
jmp .convert_done jmp .convert_done
.grayscale_alpha2_16bit: .grayscale_alpha2_16bit:
@ -979,12 +1049,17 @@ local .l1
mov [.i], ecx mov [.i], ecx
.grayscale_alpha2_16bit.extloop: .grayscale_alpha2_16bit.extloop:
init_block init_block
add eax, eax
add eax, edi add eax, edi
push eax push eax
mov ax, [esi] lodsw
add esi, 4
convert_16_to_8 convert_16_to_8
block_byte_innerloop .grayscale_alpha2_16bit.extloop mov ecx, eax
lodsw
convert_16_to_8
mov ah, cl
xchg al, ah
block_word_innerloop .grayscale_alpha2_16bit.extloop
ja .grayscale_alpha2_16bit ja .grayscale_alpha2_16bit
.convert_done: .convert_done:
; next interlace pass ; next interlace pass
@ -1070,7 +1145,7 @@ local .l1
jz .graypal_common jz .graypal_common
mov edx, 0xFFFFFF mov edx, 0xFFFFFF
.graypal_common: .graypal_common:
xor eax, eax mov eax, 0xff000000
@@: @@:
stosd stosd
add eax, edx add eax, edx