; Bitmap to Image convertion, Copr. 1994 Matthias K”ppe

		LOCALS	@@

	.286

TBitmap		STRUC
  bmType	DW	?
  bmWidth	DW	?
  bmHeight	DW	?
  bmWidthBytes	DW	?
  bmPlanes	DB	?
  bmBitsPixel	DB	?
  bmBits	DD	?
  bmPalette	DD	?
  bmFast	DD	?
TBitmap		ENDS

DATA		SEGMENT WORD PUBLIC

		ASSUME	DS: DATA

		EXTRN	Bmp2ImgRowProc: WORD, \
			BkColor: WORD, Color: WORD

DATA		ENDS

CODE		SEGMENT BYTE PUBLIC

		ASSUME	CS: CODE

		PUBLIC	Bmp2ImgRow_16, Bmp2ImgRow_256, DoBitmapToImage

	;
	; Bitmap to Image
	;

DoBitmapToImage	PROC NEAR
		ARG	Palette: DWORD, Image: DWORD, Bitmap: DWORD = ArgSize
		LOCAL	PalCopy: BYTE: 256, TheProc: WORD, \
			Lines: WORD, Delta: Word = LocalSize
		enter	LocalSize, 0

		les	di, Bitmap
		mov	cl, es:[di].TBitmap.bmBitsPixel
		mov	ax, 1
		shl	ax, cl			; palette size
		xchg	ax, cx
		cmp	ch, 0
		jz	SHORT @@2
		mov	cx, 256
@@2:
	; get the palette

		cld
		mov	bx, ds
		lds	si, Palette
		lea	di, PalCopy
		call	NEAR PTR CreatePalette

	; create proc address copy

		mov	ax, Bmp2ImgRowProc
		mov	TheProc, ax

	; load information

		les	di, Bitmap
		mov	bx, es:[di].TBitmap.bmWidthBytes
		mov	cl, es:[di].TBitmap.bmBitsPixel
		mov	ch, es:[di].TBitmap.bmPlanes
		mov	al, ch
		xor	ah, ah
		mul	bx
		mov	Delta, ax
		mov	ax, es:[di].TBitmap.bmWidth
		dec	ax
		mov	dx, es:[di].TBitmap.bmHeight
		push	ds
		lds	si, es:[di].TBitmap.bmBits
		les	di, Image

		or	dx, dx
		jns	SHORT @@4

	; skip to lowest bitmap row

		not	dx			; == neg/dec
		push	dx ax
		mov	ax, dx
		mul	Delta
		add	si, ax			; need to handle DX
		pop	ax dx
		neg	Delta
		jmp	SHORT @@3

@@4:		dec	dx

	; create image header

@@3:		stosw
		xchg	ax, dx
		stosw

		inc	ax			; line count
		mov	Lines, ax
		inc	dx
		mov	ax, bx
		lea	bx, PalCopy

	; convertion loop

@@1:		push	ax cx dx
		call	TheProc
		pop	dx cx ax
		add	si, Delta
		dec	Lines
		jnz	@@1

	; done

		pop	ds
		leave
		retn	ArgSize
DoBitmapToImage	ENDP

	; Create Palette
	;
	; In:	cl	bmBitsPixel
	;	ss:di	room for local copy (256 bytes)
	;	ds:si	palette
	;	bx	SEG DATA
	;
	; Out:	ds	SEG DATA
	;       regs	destroyed

CreatePalette	PROC NEAR
		mov	ax, ss
		mov	es, ax
		mov	ax, ds
		or	ax, si
		jnz	SHORT @@3

	; create a palette

		mov	ds, bx
		cmp	cx, 2
		ja	SHORT @@5

	  ; monochrome: use BkColor and Color

		mov	ah, BYTE PTR BkColor
		mov	al, BYTE PTR Color
		stosw
		retn

	  ; colored: create original map

@@5:		xor	al, al
@@6:		stosb
		inc	al
		loop	@@6
		retn

	; copy palette

@@3:		inc	cx
		shr	cx, 1
		rep	movsw
		mov	ds, bx
		retn
CreatePalette	ENDP

	; Bitmap to Image Row
	;
	; In:	cl	bmBitsPixel
	;	ch	bmPlanes
	;	ds:si	bitmap bits
	;	es:di	image row buffer
	;	ax	bmWidthBytes
	;	dx	bmWidth
	;	ss:bx	Palette
	;
	; Out:	ds:si	saved
	;	es:di	counted forward
	;	ss:bx	saved
	;	Regs	destroyed

	;
	; 16-color image version
	;

Bmp2ImgRow_16	PROC NEAR

		cmp	cx, 0101H
		jnz	@@T4

	;
	; 1 bit per pixel			!bx, !cx, !dx!
	;

		dec	dx
		shr	dx, 3
		inc	dx			; dest width / bytes

		push	cx
		mov	ax, ss:[bx]		; palette
		shl	ax, 4
		or	ah, 1000B		; sentinel

@@12:		shl	ah, 1
		jz	SHORT @@13
		mov	cx, dx			; dest width
		jc	SHORT @@11

		shl	al, 1
		jc	SHORT @@15

	; zero plane

		push	ax
		xor	al, al
		rep	stosb
		pop	ax
		jmp	@@12

	; negative copy

@@15:		push	ax
		push	si
@@16:		lodsb
		not	al
		stosb
		loop	@@16
		pop	si
		pop	ax
		jmp	@@12

@@11:    	shl	al, 1
		jnc	SHORT @@17

	; fill plane

		push	ax
		mov	al, 0ffh
		rep	stosb
		pop	ax
		jmp	@@12

	; copy plane

@@17:		push	si
		rep	movsb
		pop	si
		jmp	@@12

	; done

@@13:		pop	cx
		retn

	; test for 4 bits per pixel

@@T4:		cmp	cx, 0104H
		jnz	SHORT @@T8

	;
	; 4 bits per pixel			!bx, cx!, dx!, !bp
	;

		mov	dx, 8008H
		mov	cx, ax

@@44:		push	si cx

@@43:		lodsb

		push	dx
		mov	dl, al
		and	al, 1111b
		segss	xlatb
		xchg	dl, al
		shr	al, 4
		segss	xlatb
		shl	al, 4
		or	al, dl
		pop	dx

		test	al, dh			; upper nibble bit mask
		jz	SHORT @@41		; CF clear
		stc				; set CF
@@41:		rcl	ah, 1
		test	al, dl			; lower nibble bit mask
		jz	SHORT @@42		; CF clear
		stc				; set CF
@@42:		rcl	ah, 1
		dec	cx
		test	cl, 3
		jnz	@@43

		xchg	al, ah
		stosb				; store byte
		or	cx, cx
		jnz	@@43

		pop	cx si
		shr	dx, 1
		jnc	@@44

		retn

	; test for 8 bits per pixel

@@T8:		cmp	cx, 0108H
		jnz     SHORT @@T41

	;
	; 8 bits per pixel: use nearest-color table	!bx, cx!, dx!, !bp
	;

		mov	dl, 08h
		mov	cx, ax

@@84:		push	si cx
@@86:
		mov	ah, 1			; sentinel

@@83:		lodsb
		segss	xlatb

		test	al, dl			; test color bit
		jz	SHORT @@81		; CF clear
		stc				; set CF
@@81:		rcl	ah, 1
		jc	@@85

		dec	cx
		jnz	@@83
		inc	cx
@@85:
		xchg	al, ah
		stosb				; store byte
		dec	cx
		jnz	@@86

		pop	cx si
		shr	dl, 1
		jnc	@@84

		retn

	;
	; 4 planes, 1 bit per pixel: re-align data
	;

@@T41:		cmp	cx, 0401H
		jnz	SHORT @@0

		add	dx, 7
		mov	cx, dx
		mov	dx, 4
		cld
		push	si
		add	si, ax
		add	si, ax
		add	si, ax
@@P2:		push	si cx
		shr	cx, 4
		rep	movsw
		jnc	SHORT @@P1
		movsb
@@P1:		pop	cx si
		sub	si, ax
		dec	dx
		jnz	@@P2
		pop	si
		retn

@@0:
		retn
Bmp2ImgRow_16	ENDP

	;
	; 256-color image version
	;

Bmp2ImgRow_256	PROC NEAR
		cmp	cl, 1
		jnz	SHORT @@T4

	; 1 bit per pixel			!bx, cx!, !dx!

		push	bx
		mov	bx, ss:[bx]
		push	si dx
		shr	dx, 3
@@11:		lodsb
		mov	cx, 8
@@12:		shl	al, 1
		jnc	SHORT @@13
		mov	es:[di], bh
		inc	di
		loop	@@12
		dec	dx
		jnz	@@11
		jmp	SHORT @@14
@@13:		mov	es:[di], bl
		inc	di
		loop	@@12
		dec	dx
		jnz	@@11
@@14:		pop	cx
		and	cx, 7
		jz	SHORT @@17
		lodsb
@@15:		shl	al, 1
		jnc	SHORT @@16
		mov	es:[di], bh
		inc	di
		loop	@@15
		jmp	SHORT @@17
@@16:		mov	es:[di], bl
		inc	di
		loop	@@15
@@17:		pop	si bx
		retn

@@T4:		cmp	cl, 4
		jnz	SHORT @@T8

	; 4 bits per pixel			!bx, !dx!

		push	si
@@41:		lodsb
		mov	ah, al
		shr	al, 4
		segss	xlatb
		stosb
		sub	dx, 2
		jb	SHORT @@42
		mov	al, ah
		lahf
		and	al, 1111b
		segss	xlatb
		stosb
		sahf
		jnz	@@41
@@42:		pop	si
		retn

@@T8:		cmp	cl, 8
		jnz	SHORT @@0

	; 8 bits per pixel			!bx, cx!, !dx

		mov	cx, dx			; width
		push	si
@@81:		lodsb
		segss	xlatb
		stosb
		loop	@@81
		pop	si

@@0:		retn
Bmp2ImgRow_256	ENDP

CODE		ENDS

		END
