Author Topic: Raw Extraction of RGB colors values from a bmp image  (Read 60 times)

aw27

  • Member
  • ****
  • Posts: 852
  • Let's Make ASM Great Again!
Raw Extraction of RGB colors values from a bmp image
« on: December 04, 2017, 05:22:57 AM »
Using Irvine Library ( :dazzled:) and without using any of the API functions, namely GetPixel.
This demo is only for 24-bit color classical BMP files (99% of them) and the bitmaps are bottom-up. The output displays "3 arrays , one for each color value of the RGB" (as per the previous exercise), but now top-down. The attachment includes a small BMP file with 4 colours.

Code: [Select]

INCLUDE Irvine32.inc

LPVOID TYPEDEF PTR VOID
MAXFILEBYTES EQU 9523200 ; Maximum 1920x1240*4 (change if not enough)

BITMAPFILEHEADER STRUCT
  bfType        WORD ?
  bfSize        DWORD ?
  bfReserved1   WORD ?
  bfReserved2   WORD ?
  bfOffBits     DWORD ?
BITMAPFILEHEADER ENDS

BITMAPINFOHEADER STRUCT
  biSize            DWORD ?
  biWidth           SDWORD ?
  biHeight          SDWORD ?
  biPlanes          WORD ?
  biBitCount        WORD ?
  biCompression     DWORD ?
  biSizeImage       DWORD ?
  biXPelsPerMeter   SDWORD ?
  biYPelsPerMeter   SDWORD ?
  biClrUsed         DWORD ?
  biClrImportant    DWORD ?
BITMAPINFOHEADER ENDS

CreateFileW PROTO, lpFilename:PTR, dwDesiredAccess:DWORD, dwShareMode:DWORD,
lpSecurityAttributes:PTR,
dwCreationDisposition:DWORD,
dwFlagsAndAttributes:DWORD,
hTemplateFile:HANDLE

.data
fileName dw "m","i","n","i","2","4",".","b","m","p",0,0
bmpBufferPtr LPVOID ?
heapHandle HANDLE ?
fileHandle HANDLE ?
bytesReadFromFile DWORD ?
bmpWidth  DWORD ?
bmpHeight SDWORD ?
bmpBitsPerPixel WORD ?
pixelArrayStart LPVOID ?
redArray LPVOID ?
greenArray LPVOID ?
blueArray LPVOID ?
bytesperPixel DWORD ?
msgRed db "Red Color Array:",13,10,0
msgGreen db "Green Color Array:",13,10,0
msgBlue db "Blue Color Array:",13,10,0

.code

printArrays PROC
mov eax, bmpWidth
mul bmpHeight
mov ebx, eax
push ebx
call Crlf
lea edx, msgRed
call WriteString
call Crlf
mov edx, 0
mov esi, redArray

.WHILE edx<ebx
push ebx
push edx
push esi
mov al, BYTE PTR [esi]
call WriteDec
mov eax, ebx
sub eax, edx
.IF eax!=1
mov al, ','
call WriteChar
mov al, ' '
call WriteChar
.ENDIF
pop esi
pop edx
pop ebx
inc edx
inc esi
.ENDW

call Crlf
call Crlf
lea edx, msgGreen
call WriteString
call Crlf
pop ebx
push ebx
mov edx, 0
mov esi, greenArray
.WHILE edx<ebx
push ebx
push edx
push esi
mov al, BYTE PTR [esi]
call WriteDec
mov eax, ebx
sub eax, edx
.IF eax!=1
mov al, ','
call WriteChar
mov al, ' '
call WriteChar
.ENDIF
pop esi
pop edx
pop ebx
inc edx
inc esi
.ENDW

call Crlf
call Crlf
lea edx, msgBlue
call WriteString
call Crlf
pop ebx
mov edx, 0
mov esi, blueArray
.WHILE edx<ebx
push ebx
push edx
push esi
mov al, BYTE PTR [esi]
call WriteDec
mov eax, ebx
sub eax, edx
.IF eax!=1
mov al, ','
call WriteChar
mov al, ' '
call WriteChar
.ENDIF
pop esi
pop edx
pop ebx
inc edx
inc esi
.ENDW
ret
printArrays ENDP

loadBMPFromDisk PROC fName : PTR
INVOKE HeapAlloc, heapHandle, 0, MAXFILEBYTES
.IF eax==0
ret
.ENDIF
mov bmpBufferPtr, eax

INVOKE CreateFileW, fName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
.IF eax==INVALID_HANDLE_VALUE
mov eax, 0
ret
.ENDIF
mov fileHandle, eax
mov edx, bmpBufferPtr
mov ecx, MAXFILEBYTES
call ReadFromFile
.IF eax==0
ret
.ENDIF
INVOKE CloseHandle, fileHandle
ret
loadBMPFromDisk ENDP

main PROC

INVOKE GetProcessHeap
.IF eax==0
jmp @exit1
.ENDIF
mov heapHandle, eax

INVOKE loadBMPFromDisk, ADDR fileName
.IF EAX==0
jmp @exit1
.ENDIF
; Allocate space fo Color Arrays
INVOKE HeapAlloc, heapHandle, 0, MAXFILEBYTES / 3 +1
.IF eax==0
jmp @exit2
.ENDIF
mov redArray, eax
INVOKE HeapAlloc, heapHandle, 0, MAXFILEBYTES / 3+1
.IF eax==0
jmp @exit3
.ENDIF
mov greenArray, eax
INVOKE HeapAlloc, heapHandle, 0, MAXFILEBYTES / 3+1
.IF eax==0
jmp @exit4
.ENDIF
mov blueArray, eax


mov esi, bmpBufferPtr
.IF WORD PTR [esi]!="MB"
jmp @exit5
.ENDIF


mov eax, (BITMAPFILEHEADER PTR [esi]).bfOffBits
add eax, esi
mov pixelArrayStart, eax
add esi, SIZEOF BITMAPFILEHEADER

mov eax, (BITMAPINFOHEADER PTR [esi]).biWidth
mov bmpWidth, eax
mov eax, (BITMAPINFOHEADER PTR [esi]).biHeight
mov bmpHeight, eax

mov ax, (BITMAPINFOHEADER PTR [esi]).biBitCount
mov bmpBitsPerPixel, ax

cmp bmpHeight,0
jbe @endIf2 ; we will only deal with bottom-up (the normal BMP)
; go to "top"
mov eax, bmpWidth
mov ecx, bmpHeight
dec ecx ; position at the start of last scan line
mul ecx
cmp bmpBitsPerPixel, 24
jz @F ; we will deal only with 24 bit-bitmap
jmp @exit5
@@:
lea eax, [eax+2*eax]
mov ecx, 3

mov DWORD PTR bytesperPixel, ecx
mov esi, pixelArrayStart

add esi, eax
mov ebx, bmpHeight
dec ebx
@startWhile:
cmp ebx, 0
jl @endWhile
push esi

mov ecx, bmpHeight
dec ecx
sub ecx, ebx
mov eax, bmpWidth
mul ecx
mov edx, eax

mov ecx,0
.WHILE ecx<bmpWidth
NOP ; Masm bug fix

mov edi, blueArray
add edi,edx
add edi,ecx

mov al, BYTE PTR [esi]
mov BYTE PTR [edi], al

inc esi
mov edi, greenArray
add edi,edx
add edi,ecx
mov al, BYTE PTR [esi]
mov BYTE PTR [edi], al

inc esi
mov edi, redArray
add edi,edx
add edi,ecx
mov al, BYTE PTR [esi]
mov BYTE PTR [edi], al

inc esi
inc ecx
.ENDW
pop esi
mov eax, bmpWidth
mul bytesperPixel
sub esi, eax
dec ebx
jmp @startWhile
@endWhile:
@endIf2:
call printArrays

@exit5:
INVOKE HeapFree, heapHandle, 0, blueArray
@exit4:
INVOKE HeapFree, heapHandle, 0, greenArray
@exit3:
INVOKE HeapFree, heapHandle, 0, redArray
@exit2:
INVOKE HeapFree, heapHandle, 0, bmpBufferPtr
@exit1:
ret
main ENDP

END main