Files
30dayMakeOS/30_day/gview/bmp.nasm
2016-05-20 14:05:13 +08:00

647 lines
13 KiB
NASM
Raw Permalink Blame History

; BMP decode routine by I.Tak. 2003
section .text align=1
[bits 32]
;BMP File Structure (I can't understand MS.)
struc BMP
;FILE HEADER
.fType: resw 1 ;BM
.fSize: resd 1 ;whole file size
resd 1 ;reserved
.fOffBits: resd 1 ;offset from file top to image
;INFO HEADER
.iSize: resd 1 ;INFO HEADER size
.iWidth: resd 1 ;Image Width in pixels
.iHeight: resd 1 ;Image Height in pixels
.iPlanes: resw 1 ;must be 1
.iBitCount: resw 1 ;BitPerPixel 1, 4, 8, 24 (and 15,16 for new OS/2 ?)
.iCompression: resd 1 ;Compress Type. 0 for none, then SizeImage=0
.iSizeImage: resd 1 ;Image Size(compressed)
.iXPPM: resd 1 ;X Pixel Per Meter
.iYPPM: resd 1
.iClrUsed: resd 1 ;Number of used ColorQuad (0 for whole Quad)
.iClrImportant: resd 1 ;Number of Important ColorQuad.
endstruc
struc BMPOS2
;FILE HEADER
.fType: resw 1 ;BM
.fSize: resd 1 ;whole file size
resd 1 ;reserved
.fOffBits: resd 1 ;offset from file top to image
;CORE HEADER
.iSize: resd 1 ;CORE HEADER size
.iWidth: resw 1 ;Image Width in pixels
.iHeight: resw 1 ;Image Height in pixels
.iPlanes: resw 1 ;must be 1
.iBitCount: resw 1 ;BitPerPixel 1, 4, 8, 24 (and 15,16 for new OS/2 ?)
endstruc
; B/W bmp can also have palettes. The first for 0, second for 1.
struc CQuad
.b: resb 1
.g: resb 1
.r: resb 1
resb 1 ;reserved
endstruc
%if 0
int info_BMP(struct DLL_STRPICENV *env, int *info, int size, UCHAR *fp);
/* 1 (0?), 0 */
int decode0_BMP(struct DLL_STRPICENV *env, int size, UCHAR *fp,
int b_type, UCHAR *buf, int skip);
/* 0 */
envは64KBのワークエリアである8dwは返り値用になっている
, 使JPEG_initで
base_imgを作るのはdecodeのときだけでいいと思う
%endif
[absolute 0] ;naskなら[section .bss] org 0 かな win32だからダメか
bmpinfo:
.regs: resd 4
.reteip: resd 1
.env: resd 1
.info: resd 1
.size: resd 1
.module: resd 1
[absolute 0]
info:
.type: resd 1 ;1 for BMP, 2 for JPEG
resd 1 ;0
.width: resd 1
.height: resd 1
[section .text]
[global _info_BMP]
_info_BMP:
push ebx
push ebp
push esi
push edi
mov esi, [esp+bmpinfo.module]
mov eax, [esp+bmpinfo.size]
call bmpHeader
test edi, edi
jz .ret
mov esi, [esp+bmpinfo.info]
mov [esi+info.width], eax
mov [esi+info.height], ecx
mov [esi+info.type], edi ;=1
dec edi
mov [esi+info.type+4], edi ;=0
inc edi
.ret: mov eax, edi
pop edi
pop esi
pop ebp
pop ebx
ret
;in: esi=module, eax=size
;ret:eax=width, ecx=hegiht, edx=paletteSize, ebx=palette
; ebp=bpp, esi=endOfImage, edi=successFlag
bmpHeader:
lea edx, [esi+eax] ;moduleEnd
xor edi, edi
push edx
xor edx, edx
cmp eax, byte BMP.iSize+4
jbe ..@ret ;中継してしまう
cmp word[esi],'BM'
je .notMAC
sub esi, byte -128
add eax, byte -128
pop ebx
push eax
cmp eax, byte BMP.iSize+4
..@ret: jbe .ret
cmp word[esi], 'BM'
jne .ret
.notMAC:
;;MS,OS/2 フォーマット確認
mov ecx, [esi +BMP.iSize]
cmp ecx, byte 12 ;OS/2 format.
jne .MS
cmp eax, byte BMPOS2_size
jbe .ret ;coreヘッダなし
lea ebx, [esi+ecx+14] ;palette
movzx eax, word[esi+BMPOS2.iWidth] ;width
movzx ecx, word[esi+BMPOS2.iHeight] ;height
movzx ebp, word[esi+BMPOS2.iBitCount] ;bpp
mov dl, 3 ;paletteSize
jmp short .endif
.MS: cmp eax, byte BMP_size
jbe .ret ;infoヘッダなし
lea ebx, [esi+ecx+14]
sub ecx,byte 40
jne .ret ;unknownFormat
cmp ecx, [esi+BMP.iCompression]
jne .ret ;Compressed.
mov eax, [esi+BMP.iWidth] ;width
mov ecx, [esi+BMP.iHeight] ;height
movzx ebp, word[esi +BMP.iBitCount] ;bpp
mov dl, 4 ;paletteSize
.endif:
add esi, [esi +BMP.fOffBits]
;sizeが小さい場合heightを削ってで<E381A6>
;読めると答えるべきだろう。今はエラー
push edx
push eax
mul ebp ;eax=width*bpp
add eax, byte 7
shr eax, 3 ;lineSizeWithoutPudding
mov edx, eax
add eax, byte 3 ;size<1GBを仮定してedxを無<E38292>
and al, -4 ;lineSizeWithPudding
sub edx, eax ;-puddingSize
push edx
mul ecx
pop edx
add esi, eax
add esi, edx ;最終行の最後にはpuddingがないと見るべき
cmp esi, [esp+8] ;endOfModule
pop eax
ja .ret2
sub esi, edx ;esi=endOfImage
inc edi ;succeeded!
.ret2: pop edx
.ret: add esp, byte 4
ret
;***************************************************************
; 小ささ優先で作っているが, 速さ優先で作った昔のよりいいかも。
; 品質最低の高速モードのみ作ってい<E381A6>
[absolute 0]
decode:
.regs: resd 4
.reteip: resd 1
.env: resd 1
.size: resd 1
.module: resd 1
.outputType: resd 1
.dest: resd 1
.skip: resd 1
[section .text]
[global _decode0_BMP]
_decode0_BMP:
push ebx
push ebp
push esi
push edi
mov esi, [esp+decode.module]
mov eax, [esp+decode.size]
call bmpHeader
;ret:eax=width, ecx=hegiht, edx=paletteSize, ebx=palette
; ebp=bpp, esi=endOfImage, edi=successFlag
test edi,edi
jz .error
mov edi, [esp+decode.dest]
push dword[esp+decode.outputType]
push dword[esp+4+decode.skip]
push ecx ;height
push eax
push edx
mul ebp
add eax, byte 31
shr eax, 3
and al, -4
push eax
mov edx, ebp
mov ebp, esp
call bmp2beta ;ecx!=0 for error
add esp, byte bb.size
mov eax, ecx
test ecx, ecx
jz .ret
.error: push byte 1
pop eax
.ret: pop edi
pop esi
pop ebp
pop ebx
ret
[absolute -4*2]
bb:
.col0: resd 1 ;bpp1で使う
.reteip: resd 1
.sw: resd 1 ;byte
.paletteSize: resd 1 ;byte
.w: resd 1 ;pixel
.h: resd 1
.s: resd 1
.t: resd 1
.size: equ $-$$
[section .text]
;eax=?, ecx=height, edx=bpp, ebx=palette
;ebp=bb, esi=endOfImage, edi=dest
bmp2beta:
mov al, [ebp+bb.t]
and al, 0x7f
cmp al, 2
je near buf16
cmp al, 4
je buf32
mov ecx, esp ;!=0
ret
;===============================================================
; Buffer mode 4
;===============================================================
buf32:
dec edx
je near .bpp1
sub edx, byte 4-1
je .bpp4
sub edx, byte 8-4
je .bpp8
sub edx, byte 24-8
je .bpp24
mov ecx, esp ;!=0
ret
;---------------------------------------------------
; 24bpp BMP to 4byte bufer
;---------------------------------------------------
.bpp24:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
;bb.w=width(pixel), bb.s=skipByte, bb.h=height
;bb.t=outputType, bb.sw=sourceWidthByte
.do24.1:
sub esi, [ebp+bb.sw] ;esi=startOfLine
push ecx
push esi
mov ecx, [ebp+bb.w]
.do24.2:
mov al, [esi]
mov [edi+3], dl
mov [edi], al
mov al, [esi+1]
mov [edi+1], al
mov al, [esi+2]
mov [edi+2], al
add esi, byte 3
add edi, byte 4
dec ecx
jnz .do24.2
pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do24.1
ret
;---------------------------------------------------
; 8bpp BMP to 4byte buffer
;---------------------------------------------------
.bpp8:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
;pallete変換
mov dl, 255
mov eax, [ebp+bb.paletteSize]
sub ebx, eax
shl eax, 8
add ebx, eax ;ebx += paletteSize*255
.do8.1:
mov eax, [ebx]
sub ebx, [ebp+bb.paletteSize]
and eax, 0x00ffffff
dec edx
push eax
jns .do8.1
.do8.2:
sub esi, [ebp+bb.sw] ;esi=firstLineStart
push ecx
push esi
mov ecx, [ebp+bb.w]
.do8.3:
xor eax, eax
add edi, byte 4
mov al, [esi]
inc esi
;AGI stole
mov eax, [esp+eax*4+8]
dec ecx
mov [edi-4], eax
jnz .do8.3
pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do8.2
add esp, 256*4 ;palette
ret
;---------------------------------------------------
; 4bpp BMP to 4byte buffer
;---------------------------------------------------
.bpp4:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
;pallete変換
mov dl, 16
mov eax, [ebp+bb.paletteSize]
sub ebx, eax
shl eax, 4
add ebx, eax ;ebx+=eax*15
.do4.1
mov eax, [ebx]
sub ebx, [ebp+bb.paletteSize]
and eax, 0x00ffffff
dec edx
push eax
jnz .do4.1
.do4.2:
sub esi, [ebp+bb.sw] ;esi=firstLineStart
push ecx
push esi
mov ecx, [ebp+bb.w]
.do4.3:
xor edx, edx
mov al, [esi]
mov dl, al
inc esi
shr dl, 4
and eax, byte 15
add edi, byte 4
dec ecx
mov edx, [esp+edx*4+8]
mov eax, [esp+eax*4+8]
mov [edi-4], edx
jz .wend
mov [edi], eax
add edi, byte 4
dec ecx
jnz .do4.3
.wend: pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do4.2
add esp, 16*4 ;palette
ret
;---------------------------------------------------
; 1bpp BMP to 4byte buffer
;---------------------------------------------------
.bpp1:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
;pallete変換
mov eax, [ebx]
add ebx, [ebp+bb.paletteSize]
and eax, 0x00ffffff
mov ebx, [ebx]
and ebx, 0x00ffffff
xor ebx, eax
;push ebx
push eax
.do1.1:
sub esi, [ebp+bb.sw] ;esi=firstLineStart
push ecx
push esi
mov ecx, [ebp+bb.w]
.do1.2:
mov dl, [esi]
inc esi
push esi
mov esi, 8
.do1.3:
add edi, byte 4
add dl, dl
sbb eax, eax
and eax, ebx
xor eax, [ebp+bb.col0]
dec ecx
mov [edi-4], eax
jz .wend1bpp
dec esi
jnz .do1.3
pop esi
jmp short .do1.2
.wend1bpp:pop ecx
pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do1.1
pop eax
ret
;===============================================
; Buffer mode 2byte
;===============================================
buf16:
dec edx
je near .bpp1
sub edx, byte 4-1
je near .bpp4
sub edx, byte 8-4
je .bpp8
sub edx, byte 24-8
je .bpp24
mov ecx, esp
ret
;---------------------------------------------------
; 24bpp BMP to 2byte bufer
;---------------------------------------------------
.bpp24:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
.do24.1:
sub esi, [ebp+bb.sw] ;esi=startOfLine
push ecx
push esi
mov ecx, [ebp+bb.w]
.do24.2:
mov al, [esi+2]
shl eax, 16
mov ax, [esi]
add esi, byte 3
;減色処理 eax=24bitColor, edx=work, ecx=counter, ebx=work
;川合さんの趣味で没ったルーチンを持ってくるもよし(ぉ
;誤差拡散ルーチンを持ってくるもよし
shr ah, 2 ;???????? RRRRRrrr 00GGGGGG BBBBBbbb
inc edi
shr eax, 3 ;000????? ???RRRRR rrr00GGG GGGBBBBB
shl ax, 5 ;000????? ???RRRRR GGGGGGBB BBB00000
inc edi
shr eax, 5 ;00000000 ???????? RRRRRGGG GGGBBBBB
dec ecx
mov [edi-2], ax
jnz .do24.2
pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do24.1
ret
;---------------------------------------------------
; 8bpp BMP to 2byte buffer
;---------------------------------------------------
.bpp8:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
;pallete変換
mov dl, 255
mov eax, [ebp+bb.paletteSize]
sub ebx, eax
shl eax, 8
add ebx, eax ;ebx += paletteSize*255
.do8.1:
mov eax, [ebx]
sub ebx, [ebp+bb.paletteSize]
call .paletteConv
dec edx
push eax
jns .do8.1
.do8.2:
sub esi, [ebp+bb.sw] ;esi=firstLineStart
push ecx
push esi
mov ecx, [ebp+bb.w]
.do8.3:
xor eax, eax
add edi, byte 2
mov al, [esi]
inc esi
;AGI stole
mov eax, [esp+eax*4+8]
dec ecx
mov [edi-2], ax
jnz .do8.3
pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do8.2
add esp, 256*4 ;palette
ret
;---------------------------------------------------
; 4bpp BMP to 2byte buffer
;---------------------------------------------------
.bpp4:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
;pallete変換
mov dl, 16
mov eax, [ebp+bb.paletteSize]
sub ebx, eax
shl eax, 4
add ebx, eax ;ebx+=eax*15
.do4.1:
mov eax, [ebx]
sub ebx, [ebp+bb.paletteSize]
call .paletteConv
dec edx
push eax
jnz .do4.1
.do4.2:
sub esi, [ebp+bb.sw] ;esi=firstLineStart
push ecx
push esi
mov ecx, [ebp+bb.w]
.do4.3:
xor edx, edx
mov al, [esi]
mov dl, al
inc esi
shr dl, 4
and eax, byte 15
add edi, byte 2
dec ecx
mov edx, [esp+edx*4+8]
mov eax, [esp+eax*4+8]
mov [edi-2], dx
jz .wend
mov [edi], ax
add edi, byte 2
dec ecx
jnz .do4.3
.wend: pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do4.2
add esp, 16*4 ;palette
ret
;---------------------------------------------------
; 1bpp BMP to 2byte buffer
;---------------------------------------------------
.bpp1:
;ecx=height, edx=0, ebx=palette
;esi=endOfImage, edi=destinationBuffer
;pallete変換
mov eax, [ebx]
add ebx, [ebp+bb.paletteSize]
call .paletteConv
push eax
mov eax, [ebx]
call .paletteConv
pop ebx
xchg eax, ebx
xor ebx, eax
push eax
.do1.1:
sub esi, [ebp+bb.sw] ;esi=firstLineStart
push ecx
push esi
mov ecx, [ebp+bb.w]
.do1.2:
mov dl, [esi]
inc esi
push esi
mov esi, 8
.do1.3:
add dl, dl
inc edi
sbb eax, eax
inc edi
and eax, ebx
xor eax, [ebp+bb.col0]
dec ecx
mov [edi-2], ax
jz .wend1bpp
dec esi
jnz .do1.3
pop esi
jmp short .do1.2
.wend1bpp:
pop ecx
pop esi
pop ecx
add edi, [ebp+bb.s]
dec ecx
jnz .do1.1
pop eax
ret
.paletteConv:
shr ah, 2
shr eax, 3
shl ax, 5
shr eax, 5
ret