CSC231 Processing BMP Images

From dftwiki3
Jump to: navigation, search

--D. Thiebaut (talk) 10:43, 20 October 2014 (EDT)


skelBmp.asm


;;; skelBmp.asm
;;; D. Thiebaut
;;; skeleton file for reading a bmp file and writing it back.
;;; largest amount of pixels read is controlled by MAXPIXEL
;;; To assemble and run, make sure the fileio2.inc file is present
;;; in the current directory:
;;;
;;; nasm -f elf skelBmp.asm
;;; ld -melf_i386 skelBmp.o -o skelBmp
;;;
;;; To process (edit) a bmp file:
;;;
;;; ./skelBmp  someFile.bmp
;;;
;;; Note that the program overwrite the image file with new pixels.
;;;

%include "fileio2.inc"		; for basic file operations
		
%assign SYS_EXIT	1
%assign MAXPIXEL	5000000

%assign RED             2
%assign GREEN           1
%assign BLUE            0       



;;; ---------------------------------------------------------
;;; data segments
;;; ---------------------------------------------------------
        section .data
errorMsg db     "Error accessing file!",0x0A
errorLen equ    $-errorMsg

	section	.bss
filename resb   255		; reserve 255 chars for filename
handle   resd	1		; file descriptor
noRead	 resd	1		; contains number of bytes read
lWidth	 resd	1		; the line width rounded to the nearest
      				; dword boundary lWidth=(((width-1)/4)+1)*4 	

;;; ----------------------------------------------------------
;;; bmp buffer starts here
;;; ----------------------------------------------------------
bmpBuf	equ	$
type	resw	1		; header
size	resd	1
resvd1	resw	1
resvd2	resw	1
offset	resd	1
;;;
size2	resd	1		; information header
width	resd	1
height	resd	1
planes	resw	1
xbits	resw	1
compr	resd	1
imgsize	resd	1
xres	resd	1
yres	resd	1
nocol	resd	1
impcol	resd	1
headLen equ	$-bmpBuf	; length of header
	
pixelBuf resb	MAXPIXEL*3	; times 3 bytes (RGB)

	
;;; ---------------------------------------------------------
;;; code area
;;; ---------------------------------------------------------
	section	.text
	global	_start

_start:
;;; --- check that user entered more than 1 argument on command line ---
	pop	ebx		; get # of arguments on command line
	cmp	ebx,1
	jg	process		; if user forgot file name, exit
	dumpStr "Syntax: progName filename"
	jmp	exit

;;; --- get filename from command line ---
process:	
	pop	ebx		; pointer to argv[0] (name of program)
	pop	ebx		; pointer to argv[1]
	mov	edi,filename	; pointer to filename
copy:	mov	al,[ebx]	; copy name of file from argv[1] to
	mov	[edi],al	; filename string, until \0 is copied
	inc	ebx
	inc	edi
	cmp	al,0
	jne	copy
	
;;; --- open file ---
        openFile filename, [handle], errorMsg, errorLen
        

;;; --- read file in buffer ---
        readFile [handle], bmpBuf, MAXPIXEL, noRead
        
;;; --- compute length of a line of pixel:
;;; line length = (( byte width+3)/4)*4 where
;;; byte width = 3 * width, since we have 3 bytes per pixel
;;; 
	mov	eax,[width]
	add	eax,[width]
	add	eax,[width]	; eax <-- 3 x width
	dec	eax		; eax
	shr	eax,2		; 
	inc	eax
	shl	eax,2
	mov	[lWidth],eax

;;; --- display status information about the file ----
;;;     displayDmem noRead, "noRead      = "
;;; 	displayDmem compr,  "compression = "
;;; 	displayDmem offset, "offset      = "
;;; 	displayDmem width,  "width       = "
;;; 	displayDmem lWidth, "lWidth      = "
;;; 	displayDmem height, "height      = "
;;; 	displayWmem xbits,  "#bits/pixel = "

;;; --------------------------------------------------------------
;;; MAIN LOOPS
;;;  for (h=0; h<height; h++)
;;;	for (w=0; w<lWidth; w++) {
;;;	    ebx = byteIndex(w,h);
;;;	    // pixel is at byte[pixelBuf+ebx+RED]
;;;	    //             byte[pixelBuf+ebx+BLUE]
;;;	    //             byte[pixelBuf+ebx+GREEN]
;;; 	}
;;; --------------------------------------------------------------
%define	h	edi
%define	w	esi

	mov	h,0
forh:	mov	eax,[height]
	cmp	h,eax
	jge	skip

	mov	w,0
forw:	cmp	w,[lWidth]
	jge	endforh

	push	h
	push	w
	call	hw2index

	;; -----------------------------------
	;; add work to be done on pixel here!
	;; -----------------------------------

        ;blue pixel component is accessible as  byte[ebx+pixelBuf+BLUE]
        ;green pixel component is accessible as byte[ebx+pixelBuf+GREEN]
        ;red pixel component is accessible as   byte[ebx+pixelBuf+RED]

        
	;; -----------------------------------
	;; end of pixel work area
	;; -----------------------------------
	
	inc	w
	jmp	forw
endforh:
	inc	h
	jmp	forh
	
skip:				
;;; --- position file pointer back to beginning of file ---
 	seek0	[handle]
	
;;; --- write contents back to file ---
 	writeBuf [handle], bmpBuf, noRead
	
;;; --- close file ---
	close	[handle]
	
;;; --- exit() ---
exit:	
	mov	eax,SYS_EXIT
	mov	ebx,0
	int	0x80		; final system call


	
;;; -------------------------------------------------------------
;;; hw2index:	converts height and width to pixel index
;;;             index returned in ebx.  Note that computation is
;;;             performed with lWidth which must be computed
;;;             separately and is the number of bytes in one line
;;;             of pixel, such that number of byte is a multiple of
;;;             4.
;;; registers modified:	 ebx
;;; -------------------------------------------------------------
hw2index:
	push	ebp
	mov	ebp,esp
	
	push	eax		; save eax and edx
	push	edx
	mov	eax,[lWidth]	
	xor	edx,edx
	mul	dword[ebp+12]	; eax = lWidth * h
	add	eax,[ebp+8]	; eax += 3*w
	add	eax,[ebp+8]
	add	eax,[ebp+8]
	mov	ebx,eax		; pass result in ebx
	
	pop	edx
	pop	eax
	pop	ebp
	
	ret	8


Fileio2.inc


;;; fileio2.inc
;;; D. Thiebaut
;;; a collection of useful macros to deal with files
;;; and read the contents of a file specified as the first
;;; argument on the command line.

	
%assign SYs_EXIT	1
%assign	SYs_WRITE	4
%assign SYs_READ	3
%assign SYs_LSEEK	19
%assign SEEKSET		0
%assign	STDOUT		1
%assign SYs_OPEN        5
%assign SYs_CLOSE	6
%assign O_RDWR          2
	

;;; --- MACRO -----------------------------------------------
;;;	writeStr message, messageLength
%macro	writeStr2 2
	mov	eax,SYs_WRITE
	mov	ebx,STDOUT
	mov	ecx,%1
	mov	edx,%2
	int	0x80
%endmacro

	
;;; --- MACRO -----------------------------------------------
;;;	dumpStr	"literal string"
%macro	dumpStr	1
	section	.data
%%string db	%1
	 db	0x0A
%%strLen equ	$-%%string
	section	.text
	writeStr2 %%string, %%strLen
%endmacro

	
;;; --- MACRO -----------------------------------------------
;;; 	openFile filename, [handle], errorMsg, errorLen
%macro	openFile 4
	mov	eax,SYs_OPEN
	mov	ebx,%1
	mov	ecx,O_RDWR
	mov	edx,0
	int	0x80		
	test	eax,eax
	jns	%%readFile
	writeStr2 %3, %4		; there was an error.  Stop!
	mov	eax,SYs_EXIT
	mov	ebx,0
	int	0x80		; final system call

%%readFile:
	mov	%2,eax
%endmacro	

	
;;; --- MACRO -----------------------------------------------
;;; 	readFile [handle], buffer, buffer-length, number-bytes-read
%macro  readFile 4
	mov	eax,SYs_READ
	mov	ebx,%1		; file descriptor in bx
	mov	ecx,%2		; buffer address
	mov	edx,%3		; max number of bytes to read
	int	0x80
	mov	[%4],eax	; save number bytes read
%endmacro

	
;;; --- MACRO -----------------------------------------------
;;; 	writeBuf [handle], buffer, noBytesToWrite	
%macro  writeBuf 3
	mov	eax,SYs_WRITE
	mov	ebx,%1
	mov	ecx,%2
	mov	edx,[%3]
	int	0x80	
%endmacro

	
;;; --- MACRO -----------------------------------------------
;;;	seek0	[handle]
%macro	seek0	1
	mov	eax,SYs_LSEEK
	mov	ebx,%1
	mov	ecx,0
	mov	edx,SEEKSET
	int	0x80
%endmacro

	
;;; --- MACRO -----------------------------------------------
;;;	close   [handle]
%macro	close   1
	mov	eax,SYs_CLOSE
	mov	ebx,%1
	int	0x80
%endmacro