kolibrios/programs/develop/libraries/libs-dev/libimg/convert.asm
Ivan Baravy db0f7a7b77 libimg: Implement more bit depth conversion routines
git-svn-id: svn://kolibrios.org@9713 a494cfbc-eb01-0410-851d-a64ba20cac60
2022-02-10 00:50:25 +00:00

804 lines
22 KiB
NASM

;;============================================================================;;
;;//// convert.asm //// (c) dunkaist, 2012,2016,2017,2020,2022 ///////////////;;
;;============================================================================;;
;; ;;
;; This file is part of Common development libraries (Libs-Dev). ;;
;; ;;
;; SPDX-License-Identifier: LGPL-2.1-or-later ;;
;; ;;
;; Libs-Dev is free software: you can redistribute it and/or modify it under ;;
;; the terms of the GNU Lesser General Public License as published by the ;;
;; Free Software Foundation, either version 2.1 of the License, or (at your ;;
;; option) any later version. ;;
;; ;;
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ;;
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public ;;
;; License for more details. ;;
;; ;;
;; You should have received a copy of the GNU Lesser General Public License ;;
;; along with Libs-Dev. If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;============================================================================;;
;;============================================================================;;
proc img.convert _src, _dst, _dst_type, _flags, _param ;;
;;----------------------------------------------------------------------------;;
;? convert _image ;;
;;----------------------------------------------------------------------------;;
;> [_src] = pointer to source image ;;
;> [_dst] = pointer to destination image, or 0 to create a new one ;;
;> [_dst_type] = Image.Type of resulting image ;;
;> [_flags] = see libimg.inc ;;
;> [_param] = depends on _flags fields, see libimg.inc ;;
;;----------------------------------------------------------------------------;;
;< eax = 0 / pointer to converted image ;;
;< ecx = error code / undefined ;;
;;============================================================================;;
locals
img dd ?
prev dd ?
endl
push ebx esi edi
mov [img], 0
mov [prev], 0
mov ebx, [_src]
@@:
mov eax, [ebx + Image.Previous]
test eax, eax
jz .loop
mov ebx, eax
jmp @b
.loop:
stdcall img.convert.layer, ebx, [_dst], [_dst_type], [_flags], [_param]
test eax, eax
jz .error
cmp [img], 0
jnz @f
mov [img], eax
@@:
mov ecx, [prev]
jecxz @f
mov [ecx + Image.Next], eax
mov [eax + Image.Previous], ecx
@@:
mov [prev], eax
push [ebx + Image.Flags]
pop [eax + Image.Flags]
push [ebx + Image.Delay]
pop [eax + Image.Delay]
mov ebx, [ebx + Image.Next]
test ebx, ebx
jnz .loop
mov eax, [img]
.error:
pop edi esi ebx
ret
endp
;;============================================================================;;
proc img.convert.layer _src, _dst, _dst_type, _flags, _param ;;
;;----------------------------------------------------------------------------;;
;? convert _image layer ;;
;;----------------------------------------------------------------------------;;
;> [_src] = pointer to source image ;;
;> [_dst] = pointer to destination image, or 0 to create a new one ;;
;> [_dst_type] = Image.Type of resulting image ;;
;> [_flags] = see libimg.inc ;;
;> [_param] = depends on _flags fields, see libimg.inc ;;
;;----------------------------------------------------------------------------;;
;< eax = 0 / pointer to converted image ;;
;< ecx = error code / undefined ;;
;;============================================================================;;
locals
fun rd 1
endl
push ebx esi edi
mov ebx, [_src]
mov eax, [ebx + Image.Type]
mov esi, [img.convert.table + 4*eax]
mov ecx, LIBIMG_ERROR_BIT_DEPTH
.next:
lodsd
test eax, eax
jz .exit
cmp eax, [_dst_type]
lodsd
jnz .next
mov [fun], eax
mov eax, [_dst]
test eax, eax
jnz @f
stdcall img.create, [ebx + Image.Width], [ebx + Image.Height], \
[_dst_type]
test eax, eax
jz .exit
mov [_dst], eax
@@:
mov edi, [eax + Image.Data]
mov esi, [ebx + Image.Data]
mov eax, [ebx + Image.Type]
stdcall [fun], [_src], [_dst]
mov eax, [_dst]
.exit:
pop edi esi ebx
ret
endp
proc img._.convert.bpp8i_to_bpp24 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
mov ebx, [ebx + Image.Palette]
sub ecx, 1
jz .bpp8i.last
@@:
movzx eax, byte[esi]
add esi, 1
mov eax, [ebx + eax*4]
mov [edi], eax
add edi, 3
sub ecx, 1
jnz @b
.bpp8i.last:
movzx eax, byte[esi]
mov eax, [ebx + eax*4]
mov [edi], ax
shr eax, 16
mov [edi + 2], al
ret
endp
proc img._.convert.bpp8i_to_bpp32 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
mov ebx, [ebx + Image.Palette]
@@:
movzx eax, byte[esi]
add esi, 1
mov eax, [ebx + eax*4]
mov [edi], eax
add edi, 4
dec ecx
jnz @b
ret
endp
proc img._.convert.bpp8g_to_bpp1 _src, _dst
mov eax, [_dst]
mov eax, [eax + Image.Palette]
mov dword[eax], 0x00000000
mov dword[eax + 4], 0xffffffff
mov edx, [ebx + Image.Height]
.bpp8g_to_bpp1.line:
mov ax, 0x0800
mov ecx, [ebx + Image.Width]
.bpp8g_to_bpp1.pixel:
shl al, 1
cmp byte[esi], 0x7f
cmc
adc eax, 0
add esi, 1
dec ah
jnz @f
mov byte[edi], al
add edi, 1
mov ax, 0x0800
@@:
dec ecx
jnz .bpp8g_to_bpp1.pixel
cmp ah, 8
je @f
mov cl, ah
shl al, cl
mov byte[edi], al
add edi, 1
@@:
dec edx
jnz .bpp8g_to_bpp1.line
ret
endp
proc img._.convert.bpp8g_to_bpp24 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
mov al, byte[esi]
mov byte[edi + 0], al
mov byte[edi + 1], al
mov byte[edi + 2], al
add esi, 1
add edi, 3
sub ecx, 1
jnz @b
ret
endp
proc img._.convert.bpp8g_to_bpp32 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
mov al, byte[esi]
mov byte[edi + 0], al
mov byte[edi + 1], al
mov byte[edi + 2], al
mov byte[edi + 3], -1
add esi, 1
add edi, 4
dec ecx
jnz @b
ret
endp
proc img._.convert.bpp24_to_bpp24 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
lea ecx, [ecx*3]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
ret
endp
proc img._.convert.bpp24_to_bpp8g _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
movzx ebx, byte[esi + 0]
movzx eax, byte[esi + 1]
add ebx, eax
movzx eax, byte[esi + 2]
add eax, ebx
mov ebx, 3
add esi, 3
div bl
mov byte[edi], al
add edi, 1
sub ecx, 1
jnz @b
ret
endp
proc img._.convert.bpp24_to_bpp32 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
lodsw
ror eax, 16
lodsb
mov ah, 0xff ; opaque
rol eax, 16
stosd
dec ecx
jnz @b
ret
endp
proc img._.convert.bpp24_to_bpp1 _src, _dst
stdcall img.convert.layer, [_src], 0, Image.bpp8g, 0, 0
test eax, eax
jz .exit
push eax
mov ecx, [_dst]
stdcall img.convert.layer, eax, ecx, [ecx+Image.Type], 0, 0
stdcall img.destroy ; arg pushed
.exit:
ret
endp
proc img._.convert.bpp32_to_bpp24 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
mov eax, [esi]
mov [edi], ax
shr eax, 16
mov [edi + 2], al
add esi, 4
add edi, 3
sub ecx, 1
jnz @b
ret
endp
proc img._.convert.bpp32_to_bpp32 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
rep movsd
ret
endp
proc img._.convert.bpp32_to_bpp1 _src, _dst
push esi
stdcall img.convert.layer, [_src], 0, Image.bpp24, 0, 0
test eax, eax
jz .exit
push eax
stdcall img.convert.layer, eax, 0, Image.bpp8g, 0, 0
mov esi, eax
stdcall img.destroy ; arg pushed
test esi, esi
jz .exit
push esi
mov ecx, [_dst]
stdcall img.convert.layer, esi, ecx, [ecx+Image.Type], 0, 0
stdcall img.destroy ; arg pushed
.exit:
pop esi
ret
endp
proc img._.convert.bpp32_to_bpp8g _src, _dst
stdcall img.convert.layer, [_src], 0, Image.bpp24, 0, 0
test eax, eax
jz .exit
push eax
mov ecx, [_dst]
stdcall img.convert.layer, eax, ecx, [ecx+Image.Type], 0, 0
stdcall img.destroy ; arg pushed
.exit:
ret
endp
proc img._.convert.bpp15_to_bpp24 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
.bpp15.intel: ; copypasted from do_rgb
push ebx ebp
sub ecx, 4
jb .bpp15.tail
align 16
.bpp15.intel.loop:
repeat 2
mov ebx, [esi]
mov al, [esi]
mov ah, [esi + 1]
add esi, 4
and al, 0x1F
and ah, 0x1F shl 2
mov ebp, ebx
mov dl, al
mov dh, ah
shr al, 2
shr ah, 4
shl dl, 3
shl dh, 1
and ebp, 0x1F shl 5
add al, dl
add ah, dh
shr ebp, 2
mov [edi], al
mov [edi + 2], ah
mov eax, ebx
mov ebx, ebp
shr eax, 16
shr ebx, 5
add ebx, ebp
mov ebp, eax
mov [edi + 1], bl
and eax, (0x1F) or (0x1F shl 10)
and ebp, 0x1F shl 5
lea edx, [eax + eax]
shr al, 2
mov ebx, ebp
shr ah, 4
shl dl, 2
shr ebx, 2
shr ebp, 7
add al, dl
add ah, dh
mov [edi + 3], al
add ebx, ebp
mov [edi + 5], ah
mov [edi + 4], bl
add edi, 6
end repeat
sub ecx, 4
jnb .bpp15.intel.loop
.bpp15.tail:
add ecx, 4
jz .bpp15.done
@@:
movzx eax, word [esi]
mov ebx, eax
add esi, 2
and eax, (0x1F) or (0x1F shl 10)
and ebx, 0x1F shl 5
lea edx, [eax + eax]
shr al, 2
mov ebp, ebx
shr ebx, 2
shr ah, 4
shl dl, 2
shr ebp, 7
add eax, edx
add ebx, ebp
mov [edi], al
mov [edi + 1], bl
mov [edi + 2], ah
add edi, 3
sub ecx, 1
jnz @b
.bpp15.done:
pop ebp ebx
mov eax, [_dst]
jmp .quit
.bpp15.amd:
push ebx ebp
sub ecx, 4
jb .bpp15.tail
align 16
.bpp15.amd.loop:
repeat 4
if (% mod 2) = 1
mov eax, dword[esi]
mov ebx, dword[esi]
else
movzx eax, word[esi]
mov ebx, eax
end if
add esi, 2
and eax, (0x1F) or (0x1F shl 10)
and ebx, 0x1F shl 5
lea edx, [eax + eax]
shr al, 2
mov ebp, ebx
shr ebx, 2
shr ah, 4
shl dl, 2
shr ebp, 7
add eax, edx
add ebx, ebp
mov [edi], al
mov [edi + 1], bl
mov [edi + 2], ah
add edi, 3
end repeat
sub ecx, 4
jnb .bpp15.amd.loop
jmp .bpp15.tail
.quit:
ret
endp
proc img._.convert.bpp16_to_bpp24 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
.bpp16.intel:
push ebx ebp
sub ecx, 4
jb .bpp16.tail
align 16
.bpp16.intel.loop:
repeat 2
mov ebx, [esi]
mov al, [esi]
mov ah, [esi + 1]
add esi, 4
and al, 0x1F
and ah, 0x1F shl 3
mov ebp, ebx
mov dl, al
mov dh, ah
shr al, 2
shr ah, 5
shl dl, 3
and ebp, 0x3F shl 5
add al, dl
add ah, dh
shr ebp, 3
mov [edi], al
mov [edi + 2], ah
mov eax, ebx
mov ebx, ebp
shr eax, 16
shr ebx, 6
add ebx, ebp
mov ebp, eax
mov [edi + 1], bl
and eax, (0x1F) or (0x1F shl 11)
and ebp, 0x3F shl 5
mov edx, eax
shr al, 2
mov ebx, ebp
shr ah, 5
shl dl, 3
shr ebx, 3
shr ebp, 9
add al, dl
add ah, dh
mov [edi + 3], al
add ebx, ebp
mov [edi + 5], ah
mov [edi + 4], bl
add edi, 6
end repeat
sub ecx, 4
jnb .bpp16.intel.loop
.bpp16.tail:
add ecx, 4
jz .bpp16.done
@@:
movzx eax, word[esi]
mov ebx, eax
add esi, 2
and eax, (0x1F) or (0x1F shl 11)
and ebx, 0x3F shl 5
mov edx, eax
shr al, 2
mov ebp, ebx
shr ebx, 3
shr ah, 5
shl dl, 3
shr ebp, 9
add eax, edx
add ebx, ebp
mov [edi], al
mov [edi + 1], bl
mov [edi + 2], ah
add edi, 3
sub ecx, 1
jnz @b
.bpp16.done:
pop ebp ebx
mov eax, [_dst]
jmp .quit
.bpp16.amd:
push ebx ebp
sub ecx, 4
jb .bpp16.tail
align 16
.bpp16.amd.loop:
repeat 4
if (% mod 2) = 1
mov eax, dword[esi]
mov ebx, dword[esi]
else
movzx eax, word[esi]
mov ebx, eax
end if
add esi, 2
and eax, (0x1F) or (0x1F shl 11)
and ebx, 0x3F shl 5
mov edx, eax
shr al, 2
mov ebp, ebx
shr ebx, 3
shr ah, 5
shl dl, 3
shr ebp, 9
add eax, edx
add ebx, ebp
mov [edi], al
mov [edi + 1], bl
mov [edi + 2], ah
add edi, 3
end repeat
sub ecx, 4
jnb .bpp16.amd.loop
jmp .bpp16.tail
.quit:
ret
endp
proc img._.convert.bpp1_to_bpp24 uses ebx, _src, _dst
locals
width rd 1
height rd 1
endl
push [ebx + Image.Width]
pop [width]
push [ebx + Image.Height]
pop [height]
mov edx, [ebx + Image.Palette]
.bpp1_to_bpp24.line:
mov ebx, [width]
.bpp1_to_bpp24.byte:
mov ah, 8
mov al, byte[esi]
add esi, 1
.bpp1_to_bpp24.bit:
xor ecx, ecx
shl al, 1
adc ecx, 0
mov ecx, [edx + 4*ecx]
mov word[edi], cx
shr ecx, 8
mov byte[edi + 2], ch
add edi, 3
sub ebx, 1
jnz @f
sub [height], 1
jnz .bpp1_to_bpp24.line
jmp .bpp1.done
@@:
sub ah, 1
jnz .bpp1_to_bpp24.bit
jmp .bpp1_to_bpp24.byte
.bpp1.done:
ret
endp
proc img._.convert.bpp1_to_bpp32 _src, _dst
stdcall img.convert.layer, [_src], 0, Image.bpp24, 0, 0
test eax, eax
jz .exit
push eax
mov ecx, [_dst]
stdcall img.convert.layer, eax, ecx, [ecx+Image.Type], 0, 0
stdcall img.destroy ; arg pushed
.exit:
ret
endp
proc img._.convert.bpp1_to_bpp8g _src, _dst
locals
width rd 1
height rd 1
endl
push [ebx + Image.Width]
pop [width]
push [ebx + Image.Height]
pop [height]
.line:
mov edx, [width]
.byte:
mov ah, 8
mov al, byte[esi]
inc esi
.bit:
xor ecx, ecx
shl al, 1
sbb ecx, 0
mov byte[edi], cl
inc edi
dec edx
jnz @f
dec [height]
jnz .line
jmp .done
@@:
dec ah
jnz .bit
jmp .byte
.done:
ret
endp
proc img._.convert.bpp8a_to_bpp1 _src, _dst
mov eax, [_dst]
mov eax, [eax + Image.Palette]
mov dword[eax], 0x00000000
mov dword[eax + 4], 0xffffffff
mov edx, [ebx + Image.Height]
.bpp8a_to_bpp1.line:
mov ax, 0x0800
mov ecx, [ebx + Image.Width]
.bpp8a_to_bpp1.pixel:
shl al, 1
cmp byte[esi], 0x7f
cmc
adc eax, 0
add esi, 2
dec ah
jnz @f
mov byte[edi], al
add edi, 1
mov ax, 0x0800
@@:
dec ecx
jnz .bpp8a_to_bpp1.pixel
cmp ah, 8
je @f
mov cl, ah
shl al, cl
mov byte[edi], al
add edi, 1
@@:
dec edx
jnz .bpp8a_to_bpp1.line
ret
endp
proc img._.convert.bpp8a_to_bpp24 _src, _dst
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
mov al, byte[esi]
mov byte[edi + 0], al
mov byte[edi + 1], al
mov byte[edi + 2], al
add esi, 2
add edi, 3
sub ecx, 1
jnz @b
ret
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:
dd Image.bpp24, img._.convert.bpp8i_to_bpp24
dd Image.bpp32, img._.convert.bpp8i_to_bpp32
dd 0
img.convert.bpp24.table:
dd Image.bpp24, img._.convert.bpp24_to_bpp24
dd Image.bpp8g, img._.convert.bpp24_to_bpp8g
dd Image.bpp32, img._.convert.bpp24_to_bpp32
dd Image.bpp1, img._.convert.bpp24_to_bpp1
dd 0
img.convert.bpp32.table:
dd Image.bpp24, img._.convert.bpp32_to_bpp24
dd Image.bpp32, img._.convert.bpp32_to_bpp32
dd Image.bpp1, img._.convert.bpp32_to_bpp1
dd Image.bpp8g, img._.convert.bpp32_to_bpp8g
dd 0
img.convert.bpp15.table:
dd Image.bpp24, img._.convert.bpp15_to_bpp24
dd 0
img.convert.bpp16.table:
dd Image.bpp24, img._.convert.bpp16_to_bpp24
dd 0
img.convert.bpp1.table:
dd Image.bpp24, img._.convert.bpp1_to_bpp24
dd Image.bpp32, img._.convert.bpp1_to_bpp32
dd Image.bpp8g, img._.convert.bpp1_to_bpp8g
dd 0
img.convert.bpp8g.table:
dd Image.bpp24, img._.convert.bpp8g_to_bpp24
dd Image.bpp32, img._.convert.bpp8g_to_bpp32
dd Image.bpp1, img._.convert.bpp8g_to_bpp1
dd 0
img.convert.bpp2i.table:
dd 0
img.convert.bpp4i.table:
dd 0
img.convert.bpp8a.table:
dd Image.bpp24, img._.convert.bpp8a_to_bpp24
dd Image.bpp32, img._.convert.bpp8a_to_bpp32
dd 0
img.convert.table:
dd 0 ; no image type zero
dd img.convert.bpp8i.table
dd img.convert.bpp24.table
dd img.convert.bpp32.table
dd img.convert.bpp15.table
dd img.convert.bpp16.table
dd img.convert.bpp1.table
dd img.convert.bpp8g.table
dd img.convert.bpp2i.table
dd img.convert.bpp4i.table
dd img.convert.bpp8a.table