35,12 → 35,9 |
include 'gif/gif.asm' |
include 'jpeg/jpeg.asm' |
include 'png/png.asm' |
include 'tga/tga.asm' |
include 'z80/z80.asm' |
|
mem.alloc dd ? |
mem.free dd ? |
mem.realloc dd ? |
dll.load dd ? |
|
;;================================================================================================;; |
proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
60,6 → 57,14 |
|
call img.initialize.jpeg |
|
xor eax, eax |
cpuid |
cmp ecx, 'ntel' |
jnz @f |
mov dword [img._.do_rgb.handlers + (Image.bpp15-1)*4], img._.do_rgb.bpp15.intel |
mov dword [img._.do_rgb.handlers + (Image.bpp16-1)*4], img._.do_rgb.bpp16.intel |
@@: |
|
.ok: xor eax,eax |
ret |
endp |
211,26 → 216,257 |
mov ecx, [esi + Image.Width] |
imul ecx, [esi + Image.Height] |
mov eax, [esi + Image.Type] |
dec eax |
jz .bpp8 |
dec eax |
jz .bpp24 |
; 32 BPP -> 24 BPP |
jmp dword [.handlers + (eax-1)*4] |
|
align 16 |
.bpp8: |
; 8 BPP -> 24 BPP |
push ebx |
mov ebx, [esi + Image.Palette] |
mov esi, [esi + Image.Data] |
@@: |
movzx eax, byte [esi] |
add esi, 1 |
mov eax, [ebx + eax*4] |
mov [edi], eax |
add edi, 3 |
sub ecx, 1 |
jnz @b |
pop ebx |
ret |
|
; 15 BPP -> 24 BPP |
.bpp15.intel: |
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 |
@@: |
mov eax, [esi] |
mov [edi], ax |
shr eax, 16 |
mov [edi+2], al |
add esi, 4 |
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 |
ret |
|
.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 |
|
; 16 BPP -> 24 BPP |
.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 |
ret |
|
.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 |
|
align 16 |
.bpp24: |
; 24 BPP -> 24 BPP |
lea ecx, [ecx*3 + 3] |
239,23 → 475,24 |
rep movsd |
ret |
|
.bpp8: |
; 8 BPP -> 24 BPP |
push ebx |
mov ebx, [esi + Image.Palette] |
align 16 |
.bpp32: |
; 32 BPP -> 24 BPP |
mov esi, [esi + Image.Data] |
|
@@: |
movzx eax, byte [esi] |
add esi, 1 |
mov eax, [ebx + eax*4] |
mov eax, [esi] |
mov [edi], ax |
shr eax, 16 |
mov [edi+2], al |
add esi, 4 |
add edi, 3 |
sub ecx, 1 |
jnz @b |
pop ebx |
|
@@: |
ret |
|
endp |
|
;;================================================================================================;; |
335,6 → 572,32 |
endp |
|
;;================================================================================================;; |
proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
;;------------------------------------------------------------------------------------------------;; |
;> --- TBD --- ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
mov eax, [_img] |
mov edx, [eax + Image.Previous] |
test edx, edx |
jz @f |
push [eax + Image.Next] |
pop [edx + Image.Next] |
@@: |
mov edx, [eax + Image.Next] |
test edx, edx |
jz @f |
push [eax + Image.Previous] |
pop [edx + Image.Previous] |
@@: |
stdcall img._.delete, eax |
ret |
endp |
|
;;================================================================================================;; |
proc img.destroy _img ;///////////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
343,8 → 606,33 |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
;TODO: link Next and Previous |
stdcall img._.delete, [_img] |
push 1 |
mov eax, [_img] |
mov eax, [eax + Image.Previous] |
.destroy_prev_loop: |
test eax, eax |
jz .destroy_prev_done |
pushd [eax + Image.Previous] |
stdcall img._.delete, eax |
test eax, eax |
jnz @f |
mov byte [esp+4], 0 |
@@: |
pop eax |
jmp .destroy_prev_loop |
.destroy_prev_done: |
mov eax, [_img] |
.destroy_next_loop: |
pushd [eax + Image.Next] |
stdcall img._.delete, eax |
test eax, eax |
jnz @f |
mov byte [esp+4], 0 |
@@: |
pop eax |
test eax, eax |
jnz .destroy_next_loop |
pop eax |
ret |
endp |
|
417,9 → 705,9 |
endp |
|
;;================================================================================================;; |
proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;; |
proc img.flip.layer _img, _flip_kind ;////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Flip image ;; |
;? Flip image layer ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _flip_kind = one of FLIP_* constants ;; |
493,12 → 781,9 |
mov esi, [ebx + Image.Data] |
mov edi, [scanline_len] |
add edi, esi |
jmp dword [.handlers_horz + (eax-1)*4] |
|
dec eax |
jz .bpp8.2 |
dec eax |
jz .bpp24.2 |
|
.bpp32_horz: |
sub edi, 4 |
|
.next_line_horz: |
521,7 → 806,29 |
jnz .next_line_horz |
jmp .exit |
|
.bpp8.2: |
.bpp1x_horz: |
sub edi, 2 |
.next_line_horz1x: |
push ecx esi edi |
|
mov ecx, [ebx + Image.Width] |
@@: mov ax, [esi] |
mov dx, [edi] |
mov [edi], ax |
mov [esi], dx |
add esi, 2 |
sub edi, 2 |
sub ecx, 2 |
ja @b |
|
pop edi esi ecx |
add esi, [scanline_len] |
add edi, [scanline_len] |
dec ecx |
jnz .next_line_horz1x |
jmp .exit |
|
.bpp8_horz: |
dec edi |
.next_line_horz8: |
push ecx esi edi |
544,13 → 851,12 |
jnz .next_line_horz8 |
jmp .exit |
|
.bpp24.2: |
.bpp24_horz: |
sub edi, 3 |
.next_line_horz32: |
.next_line_horz24: |
push ecx esi edi |
|
mov ecx, [ebx + Image.Width] |
shr ecx, 1 |
@@: |
mov al, [esi] |
mov dl, [edi] |
566,14 → 872,14 |
mov [esi+2], dl |
add esi, 3 |
sub edi, 3 |
sub ecx, 1 |
jnz @b |
sub ecx, 2 |
ja @b |
|
pop edi esi ecx |
add esi, [scanline_len] |
add edi, [scanline_len] |
dec ecx |
jnz .next_line_horz32 |
jnz .next_line_horz24 |
|
.exit: |
xor eax, eax |
588,11 → 894,42 |
endp |
|
;;================================================================================================;; |
proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////////////////////////;; |
proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Rotate image ;; |
;? Flip all layers of image ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _flip_kind = one of FLIP_* constants ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
push 1 |
mov ebx, [_img] |
@@: |
mov eax, [ebx + Image.Previous] |
test eax, eax |
jz .loop |
mov ebx, eax |
jmp @b |
.loop: |
stdcall img.flip.layer, ebx, [_flip_kind] |
test eax, eax |
jnz @f |
mov byte [esp], 0 |
@@: |
mov ebx, [ebx + Image.Next] |
test ebx, ebx |
jnz .loop |
pop eax |
ret |
endp |
|
;;================================================================================================;; |
proc img.rotate.layer _img, _rotate_kind ;////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Rotate image layer ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _rotate_kind = one of ROTATE_* constants ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
646,7 → 983,57 |
jz .rotate_ccw8 |
cmp [ebx + Image.Type], Image.bpp24 |
jz .rotate_ccw24 |
cmp [ebx + Image.Type], Image.bpp32 |
jz .rotate_ccw32 |
|
.next_column_ccw_low1x: |
dec ecx |
js .exchange_dims |
push ecx |
|
mov edx, [scanline_len_old] |
add [scanline_len_old], -2 |
|
mov ecx, [scanline_pixels_new] |
mov esi, [ebx + Image.Data] |
mov edi, [line_buffer] |
@@: mov ax, [esi] |
mov [edi], ax |
add esi, edx |
add edi, 2 |
sub ecx, 1 |
jnz @b |
|
mov eax, [scanline_pixels_new] |
mov edi, [ebx + Image.Data] |
lea esi, [edi + 2] |
mov edx, [scanline_len_old] |
@@: mov ecx, edx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
add esi, 1 |
sub eax, 1 |
jnz @b |
|
mov eax, [scanline_len_new] |
sub [pixels_ptr], eax |
mov ecx, [scanline_pixels_new] |
mov esi, [line_buffer] |
mov edi, [pixels_ptr] |
mov edx, ecx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
|
pop ecx |
jmp .next_column_ccw_low1x |
|
.rotate_ccw32: |
.next_column_ccw_low: |
dec ecx |
js .exchange_dims |
809,7 → 1196,59 |
jz .rotate_cw8 |
cmp [ebx + Image.Type], Image.bpp24 |
jz .rotate_cw24 |
cmp [ebx + Image.Type], Image.bpp32 |
jz .rotate_cw32 |
|
.next_column_cw_low1x: |
dec ecx |
js .exchange_dims |
push ecx |
|
mov edx, [scanline_len_old] |
add [scanline_len_old], -2 |
|
mov ecx, [scanline_pixels_new] |
mov esi, [pixels_ptr] |
add esi, -2 |
mov edi, [line_buffer] |
@@: mov ax, [esi] |
mov [edi], ax |
sub esi, edx |
add edi, 2 |
sub ecx, 1 |
jnz @b |
|
mov eax, [scanline_pixels_new] |
dec eax |
mov edi, [ebx + Image.Data] |
add edi, [scanline_len_old] |
lea esi, [edi + 2] |
mov edx, [scanline_len_old] |
@@: mov ecx, edx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
add esi, 3 |
sub eax, 1 |
jnz @b |
|
mov eax, [scanline_len_new] |
sub [pixels_ptr], eax |
mov ecx, eax |
mov esi, [line_buffer] |
mov edi, [pixels_ptr] |
shr ecx, 2 |
rep movsd |
mov ecx, eax |
and ecx, 3 |
rep movsb |
|
pop ecx |
jmp .next_column_cw_low1x |
|
.rotate_cw32: |
.next_column_cw_low: |
dec ecx |
js .exchange_dims |
976,8 → 1415,94 |
ret |
endp |
|
;;================================================================================================;; |
proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Rotate all layers of image ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _rotate_kind = one of ROTATE_* constants ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
push 1 |
mov ebx, [_img] |
@@: |
mov eax, [ebx + Image.Previous] |
test eax, eax |
jz .loop |
mov ebx, eax |
jmp @b |
.loop: |
stdcall img.rotate.layer, ebx, [_rotate_kind] |
test eax, eax |
jnz @f |
mov byte [esp], 0 |
@@: |
mov ebx, [ebx + Image.Next] |
test ebx, ebx |
jnz .loop |
pop eax |
ret |
endp |
|
;;================================================================================================;; |
proc img.draw _img, _x, _y, _width, _height, _xpos, _ypos ;///////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Draw image in the window ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;>_x = x-coordinate in the window ;; |
;>_y = y-coordinate in the window ;; |
;>_width = maximum width to draw ;; |
;>_height = maximum height to draw ;; |
;>_xpos = offset in image by x-axis ;; |
;>_ypos = offset in image by y-axis ;; |
;;------------------------------------------------------------------------------------------------;; |
;< no return value ;; |
;;================================================================================================;; |
push ebx esi edi |
mov ebx, [_img] |
stdcall img._.validate, ebx |
test eax, eax |
jnz .done |
mov ecx, [ebx + Image.Width] |
sub ecx, [_xpos] |
jbe .done |
cmp ecx, [_width] |
jb @f |
mov ecx, [_width] |
@@: |
mov edx, [ebx + Image.Height] |
sub edx, [_ypos] |
jbe .done |
cmp edx, [_height] |
jb @f |
mov edx, [_height] |
@@: |
mov eax, [ebx + Image.Width] |
sub eax, ecx |
call img._.get_scanline_len |
shl ecx, 16 |
add ecx, edx |
mov edx, [_x - 2] |
mov dx, word [_y] |
mov esi, [ebx + Image.Type] |
mov esi, [type2bpp + (esi-1)*4] |
mov edi, [ebx + Image.Palette] |
mov ebx, [ebx + Image.Data] |
push ebp |
push 65 |
pop ebp |
xchg eax, ebp |
int 40h |
pop ebp |
.done: |
pop edi esi ebx |
ret |
endp |
|
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below are private procs you should never call directly from your code ;; |
1015,6 → 1540,7 |
xor ecx, ecx |
mov [eax + Image.Data], ecx |
mov [eax + Image.Type], ecx |
mov [eax + Image.Flags], ecx |
mov [eax + Image.Extended], ecx |
mov [eax + Image.Previous], ecx |
mov [eax + Image.Next], ecx |
1118,7 → 1644,10 |
jz .bpp8.1 |
cmp [ebx + Image.Type], Image.bpp24 |
jz .bpp24.1 |
shl eax, 2 |
add eax, eax |
cmp [ebx + Image.Type], Image.bpp32 |
jnz @f |
add eax, eax |
jmp @f |
.bpp24.1: |
lea eax, [eax*3] |
1135,7 → 1664,7 |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
|
|
align 4 |
img._.formats_table: |
.bmp dd img.is.bmp, img.decode.bmp, img.encode.bmp |
; .ico dd img.is.ico, img.decode.ico, img.encode.ico |
1143,9 → 1672,27 |
.gif dd img.is.gif, img.decode.gif, img.encode.gif |
.png dd img.is.png, img.decode.png, img.encode.png |
.jpg dd img.is.jpg, img.decode.jpg, img.encode.jpg |
.tga dd img.is.tga, img.decode.tga, img.encode.tga |
.z80 dd img.is.z80, img.decode.z80, img.encode.z80 ;this must be the last entry as there are no |
;signatures in z80 screens at all |
dd 0 |
|
align 4 |
type2bpp dd 8, 24, 32, 15, 16 |
img._.do_rgb.handlers: |
dd img._.do_rgb.bpp8 |
dd img._.do_rgb.bpp24 |
dd img._.do_rgb.bpp32 |
dd img._.do_rgb.bpp15.amd ; can be overwritten in lib_init |
dd img._.do_rgb.bpp16.amd ; can be overwritten in lib_init |
|
img.flip.layer.handlers_horz: |
dd img.flip.layer.bpp8_horz |
dd img.flip.layer.bpp24_horz |
dd img.flip.layer.bpp32_horz |
dd img.flip.layer.bpp1x_horz |
dd img.flip.layer.bpp1x_horz |
|
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
1160,7 → 1707,7 |
|
export \ |
lib_init , 'lib_init' , \ |
0x00010003 , 'version' , \ |
0x00010004 , 'version' , \ |
img.is_img , 'img.is_img' , \ |
img.info , 'img.info' , \ |
img.from_file , 'img.from_file' , \ |
1172,11 → 1719,15 |
img.encode , 'img.encode' , \ |
img.create , 'img.create' , \ |
img.destroy , 'img.destroy' , \ |
img.destroy.layer, 'img.destroy.layer', \ |
img.count , 'img.count' , \ |
img.lock_bits , 'img.lock_bits' , \ |
img.unlock_bits , 'img.unlock_bits' , \ |
img.flip , 'img.flip' , \ |
img.rotate , 'img.rotate' |
img.flip.layer , 'img.flip.layer' , \ |
img.rotate , 'img.rotate' , \ |
img.rotate.layer, 'img.rotate.layer', \ |
img.draw , 'img.draw' |
|
; import from deflate unpacker |
; is initialized only when PNG loading is requested |
1187,11 → 1738,21 |
import kfar_arc, \ |
deflate_unpack2, 'deflate_unpack2' |
|
align 4 |
; mutex for unpacker loading |
deflate_loader_mutex dd 0 |
|
; default palette for GIF - b&w |
gif_default_palette: |
db 0, 0, 0 |
db 0xFF, 0xFF, 0xFF |
|
section '.data' data readable writable align 16 |
; uninitialized data - global constant tables |
mem.alloc dd ? |
mem.free dd ? |
mem.realloc dd ? |
dll.load dd ? |
|
; data for YCbCr -> RGB translation |
color_table_1 rd 256 |