News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Extracting RGB colors values from a bmp image

Started by M.Nabeel, December 01, 2017, 04:18:54 AM

Previous topic - Next topic

M.Nabeel

Hi guys
I'm a little new to assembly programming , in my college they teach Irvine 32 ( not so bad ) but I can't finish the simple task of loading a bmp image file and getting the values of colors of each pixel !
after days of searching , I discovered MASM 32 and some functions like : CreateDIBSection , GetDIBits , GetPixel and so on ...
The problem is I don't know what to use and how to use it !
most of this forum topics are for displaying in a window , which is unfortunately not what I want to do
Basically , I want to create an assembly DLL and attach it to a C# windows form App. , the DLL has a function that reads a bmp image (from disc of course) then return 3 arrays , one for each color value of the RGB .
please be specific and explain in details ( specially what libraries to include ) , cause as I said before , most of my experience is using irvine not masm .
It would be great if there's some sort of a tutorial or a book , would be helpful for future tasks .

hutch--

An RGB color value is in what you call a COLORREF format. 4 bytes, 3 for the RGB and the 4th unused unless you run an RGB/A alpha channel. You split the COLORREF value into the 4 bytes by loading it into a register and reading the first 2 bytes, then rotate the register with ROL or ROR by 16 bits and reading the first 2 bytes again.

M.Nabeel

Quote from: hutch-- on December 01, 2017, 07:21:49 AM
An RGB color value is in what you call a COLORREF format. 4 bytes, 3 for the RGB and the 4th unused unless you run an RGB/A alpha channel. You split the COLORREF value into the 4 bytes by loading it into a register and reading the first 2 bytes, then rotate the register with ROL or ROR by 16 bits and reading the first 2 bytes again.
I get that , I just don't know how to fill a COLORREF from an existing bmp image on disk !
A code example would be a great help .
And thanks anyway  :icon14:

raymond


Before you even start thinking about toying around with .bmp files, you MUST FIRST understand their file structure. The three main components are the BITMAPFILEHEADER, the BITMAPINFO (including its BITMAPINFOHEADER), and the RGBQUAD if applicable. You can start with the MSDN descriptions at https://msdn.microsoft.com/en-us/library/dd183371.aspx.

Then you may want to explain what you intend to do with those three arrays you intend to fill and return from your dll.
Whenever you assume something, you risk being wrong half the time.
http://www.ray.masmcode.com

M.Nabeel

Quote from: raymond on December 01, 2017, 10:18:28 AM

Before you even start thinking about toying around with .bmp files, you MUST FIRST understand their file structure. The three main components are the BITMAPFILEHEADER, the BITMAPINFO (including its BITMAPINFOHEADER), and the RGBQUAD if applicable. You can start with the MSDN descriptions at https://msdn.microsoft.com/en-us/library/dd183371.aspx.

Then you may want to explain what you intend to do with those three arrays you intend to fill and return from your dll.
I think there is a miss understanding in here , I have already implemented this whole app using C# (some image manipulation like changing brightness , modify colors , .... )
the thing is it's a bonus task if we implement some of it's functions using assemply , as I said before , I don't know much about MASM as I know about Irvine , what I'm asking for here is some help with syntax .
this what I have done so far :

;.386
;.model flat, stdcall
option casemap :none
      include \masm32\include\masm32rt.inc
      include \masm32\include\windows.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\user32.inc
      include \masm32\include\gdi32.inc
  include \masm32\include\masm32.inc
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\gdi32.lib
  includelib \masm32\lib\masm32.lib
.data

.data?
hInstance  dd ?
bmphndl dd ?
dc dd ?

.code
main:
mov eax,0                ; just to check if it's value got changed ( the only way I can debug so far :| )

  invoke GetModuleHandle,NULL
  mov hInstance,eax

  invoke LoadBitmap,hInstance,100
  mov bmphndl, eax
  print str$(eax),13,10                 ;if eax!=0 -> Load Complete Successfully

  invoke CreateCompatibleDC,NULL
  mov dc,eax

  invoke SelectObject,dc,bmphndl
  print str$(eax),13,10                ; if eax value != previous value -> Selected Successfully

  invoke GetPixel,dc,0,0           ; returns a colorref object , contains 3 colors values
 
invoke ExitProcess, 0
end main


now I think the only thing I have left is to extract the colors from the colorref , but I don't know how to use  GetRValue,......,.......
any help with the syntax would be great , I will try the method within the first reply

jj2007

Quote from: M.Nabeel on December 01, 2017, 11:19:25 AM

  invoke GetPixel,dc,0,0           ; returns a colorref object , contains 3 colors values

Check the return value in eax: This is the COLORREF. The byte sized al and ah are directly available, e.g. via movxz ebx, ah, the rest by shifting eax to the right.

M.Nabeel

Quote from: jj2007 on December 01, 2017, 11:41:28 AM
Quote from: M.Nabeel on December 01, 2017, 11:19:25 AM

  invoke GetPixel,dc,0,0           ; returns a colorref object , contains 3 colors values

Check the return value in eax: This is the COLORREF. The byte sized al and ah are directly available, e.g. via movxz ebx, ah, the rest by shifting eax to the right.

Ok , this wasn't hard at all
one last question , I want to use GetBitmapDimensionEx to get the dimensions
my code :


invoke GetBitmapDimensionEx,bmphndl,ebx


as far as I understood , ebx is now holding a pointer to a size struct that contains 2 values I need , any idea how to get those 2 values ?
or an easier way to get the dimensions ?
BTW , I'm using Visual studio 2015 .

jj2007

Quote from: M.Nabeel on December 01, 2017, 11:59:40 AMebx is now holding a pointer to a size struct that contains 2 values I need , any idea how to get those 2 values ?

mov eax, [ebx.SIZE.cx]  ; width
mov eax, [ebx.SIZE.cy]  ; height

dedndave

notice that "cx" is a reserved word in ASM, due to the register name CX
"SIZE" is also reserved

so, in windows.inc, Hutch changed the names slightly to accommodate the overlaps

_SIZE STRUCT
  x  DWORD      ?
  y  DWORD      ?
_SIZE ENDS

M.Nabeel

Quote from: jj2007 on December 01, 2017, 12:13:10 PM
Quote from: M.Nabeel on December 01, 2017, 11:59:40 AMebx is now holding a pointer to a size struct that contains 2 values I need , any idea how to get those 2 values ?

mov eax, [ebx.SIZE.cx]  ; width
mov eax, [ebx.SIZE.cy]  ; height

That's my code
invoke GetBitmapDimensionEx,bmphndl,ebx
  mov eax, [ebx.SIZE.cx]  ; width
  print str$(eax),13,10
  mov eax, [ebx.SIZE.cy]  ; height
  print str$(eax),13,10


that's the error :
Quoteundefined symbol : cx
Quoteundefined symbol : cy

M.Nabeel

Quote from: dedndave on December 01, 2017, 12:19:25 PM
notice that "cx" is a reserved word in ASM, due to the register name CX
"SIZE" is also reserved

so, in windows.inc, Hutch changed the names slightly to accommodate the overlaps

_SIZE STRUCT
  x  DWORD      ?
  y  DWORD      ?
_SIZE ENDS


tried this :
Quote
invoke GetBitmapDimensionEx,bmphndl,ebx
  mov eax, [ebx._SIZE.x]  ; width
  print str$(eax),13,10
  mov eax, [ebx._SIZE.y]  ; height
  print str$(eax),13,10

it compiles , but it crashes and displays no value !

raymond

Quoteany idea how to get those 2 values ?
or an easier way to get the dimensions ?

The answer is YES by using assembly and knowing the structure of .bmp files.

If you have loaded the bmp file into the computer, you certainly must know the address of where in memory it is located. The first 14 bytes of the file comprise the BITMAPFILEHEADER. That is followed by the BITMAPINFOHEADER which has the width and height dimensions at address 4 and 8 respectively. In case you may not be aware of their details, the following is copied from the SDK:

biWidth
The width of the bitmap, in pixels.

biHeight
The height of the bitmap, in pixels. If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.
If biHeight is negative, indicating a top-down DIB, biCompression must be either BI_RGB or BI_BITFIELDS.
Top-down DIBs cannot be compressed.


N.B. Notice the meaning of the sign for the Height dimension.

Now, for retrieving easily the bmp dimensions, assuming that the address of the file is file_add,

mov esi,offset file_add
mov eax,esi[14+4]   ;EAX now contains the width of the image
mov img_width,eax
mov eax,esi[14+8]   ;EAX now contains the height of the image
cmp eax,0
jge @F
neg eax
@@:
mov img_height,eax   


I have to assume that you are aware of the effect of the number of bits-per-pixel on the remaining structure of the bitmap.

(And I still don't know what you could intend to do with those 3 arrays returned by the dll!)
Whenever you assume something, you risk being wrong half the time.
http://www.ray.masmcode.com

jj2007

Quote from: M.Nabeel on December 01, 2017, 12:34:06 PM
it compiles , but it crashes and displays no value !

Can you show the code where you load ebx?
Sorry for the SIZE thing, I had no time to test it. Thanks to Dave.