Jump to content

Getting bitmap data


Recommended Posts

Hi!

I need to fill a BITMAPINFOHEADER structure (Exactly like $tagBITMAPINFO except the RGBQuad element), and I'm completely lost.

The delphi source I'm translating did this by using BlockRead from the bitmap directly to the struct (Me thinks that delphi is very strange), but this doesn't seem like something autoit can handle.

Any ideas?

Edited by monoceres

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

You may want to take a look at this script, it contains references to RGBQUAD, BITMAPINFO, and BITMAPINFOHEADER:

http://www.autoitscript.com/forum/index.ph...mp;#entry213739

I have been looking at this code, but it seems like its only writing files, not reading them.

I have found a c++ example, so maybe as a last resort I could create a small dll... but it would be really great to have this done in autoit, I mean the info is in there! You just have to know where to look.

Here's how delphi did it, maybe someone will get a flash of genious :)

AssignFile(BFile,"1.bmp");
     Reset(BFile,1);
     BlockRead(BFile,m_Bfh,SizeOf(m_Bfh)); // m_Bfh= BITMAPFILEHEADER, m_Bih=BITMAPINFOHEADER
     BlockRead(BFile,m_Bih,SizeOf(m_Bih));
     SetLength(m_MemBitMapInfo,m_bfh.bfOffBits - 14);
     SetLength(m_MemBits,m_Bih.biSizeImage);
     Seek(BFile,SizeOf(m_Bfh));
     BlockRead(BFile,m_MemBitMapInfo[0],length(m_MemBitMapInfo));
     CloseFile(BFile);

Any input is greatly appreciated since this has stopped my entire project :(

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Pseudo-Code:

#Include <WinAPI.au3>
$hFile = _WinAPI_CreateFile("the.bmp",1,2)
$m_Bfh= DllstructCreate(BITMAPFILEHEADER)
_WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bfh),DllStructGetSize($m_Bfh))
$m_Bih= DllstructCreate(BITMAPINFOHEADER)
_WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bih),DllStructGetSize($m_Bih))
;Now $_Bih is BITMAPINFOHEADER
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Pseudo-Code:

#Include <WinAPI.au3>
$hFile = _WinAPI_CreateFile("the.bmp",1,2)
$m_Bfh= DllstructCreate(BITMAPFILEHEADER)
_WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bfh),DllStructGetSize($m_Bfh))
$m_Bih= DllstructCreate(BITMAPINFOHEADER)
_WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bih),DllStructGetSize($m_Bih))
;Now $_Bih is BITMAPINFOHEADER
Thanks for your answer but it doesn't seem to work, all elements in the struct are 0... but I definitly think you're on the right track! :)

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Now I see why it only returns 0, it because _WinApi_createfile() overwrites my bitmap, but I still need the handle returned from it.

Why is there not a _WinApi_OpenFile()? FileOpen() doesn't seem to work...

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Now I see why it only returns 0, it because _WinApi_createfile() overwrites my bitmap, but I still need the handle returned from it.

Why is there not a _WinApi_OpenFile()? FileOpen() doesn't seem to work...

#Include <WinAPI.au3>

_WinAPI_CreateFile($sFileName, $iCreation[, $iAccess = 4[, $iShare = 0[, $iAttributes = 0[, $pSecurity = 0]]]])

$iCreation

Action to take on files that exist and do not exist:

0 - Creates a new file. The function fails if the file exists

1 - Creates a new file. If a file exists, it is overwritten

2 - Opens a file. The function fails if the file does not exist

3 - Opens a file. If the file does not exist, the function creates the file

4 - Opens a file and truncates it so that its size is 0 bytes. The function fails if the file does not exist.

$iAccess

Access to the object:

1 - Execute

2 - Read

4 - Write

$iShare

Sharing mode of an object:

1 - Delete

2 - Read

4 - Write

$hFile = _WinAPI_CreateFile("the.bmp",2,2,2)

Link to comment
Share on other sites

Aah I see, but I'm still having problems :(

My struct is now filled but it has real strange values, for example this returns that biWidth=10.

#Include <WinAPI.au3>
$BITMAPINFOHEADER = DllStructCreate("dword biSize;dword biWidth;dword biHeight;ushort biPlanes;ushort biBitCount;dword biCompression;dword biSizeImage;dword biXPelsPerMeter;dword biYPelsPerMeter;dword biClrUsed;dword biClrImportant")
$m_Bih=$BITMAPINFOHEADER
$hFile = _WinAPI_CreateFile("3.bmp",2,2,2)
Dim $readbytes
_WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bih),DllStructGetSize($m_Bih),$readbytes)
MsgBox(0,"",DllStructGetData($m_Bih,"biWidth"))

Thanks for your time :)

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

I don't know man I was having similar problems with those functions yesterday in this topic:

http://www.autoitscript.com/forum/index.php?showtopic=70124

That's too bad, I'm almost done with my function, it's a BitmapsToAvi function and this is the only thing left, I have succesfully created both file and stream.

Anyways I just need the values in the struct, maybe there is another way to query them? I currently use GetExtProperty() udf to get the width and height of bitmap, but it won't return any of the other more advanced info.

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Based on the Delphi code and the bitmap file format (http://en.wikipedia.org/wiki/BMP_file_format), you need to read the file header before you read the info header so that the file pointer will be in the correct position.

#Include <WinAPI.au3>
Global Const $tagBITMAPFILEHEADER = "ushort bfType;dword bfSize;ushort bfReserved1;ushort bfReserved2;dword bfOffBits"
Global Const $tagBITMAPINFOHEADER = "dword biSize;dword biWidth;dword biHeight;ushort biPlanes;" & _
    "ushort biBitCount;dword biCompression;dword biSizeImage;dword biXPelsPerMeter;dword biYPelsPerMeter;" & _
    "dword biClrUsed;dword biClrImportant"
    
$m_Bfh = DllStructCreate($tagBITMAPFILEHEADER)
$m_Bih = DllStructCreate($tagBITMAPINFOHEADER)
$hFile = _WinAPI_CreateFile(@ScriptDir & "\on.bmp",2,2,2)
If $hFile = 0 Then
    ConsoleWrite("! Failed to open file" & @LF)
    Exit
EndIf

Dim $readbytes
If _WinAPI_ReadFile($hFile,DllStructGetPtr($m_Bfh),DllStructGetSize($m_Bfh),$readbytes) Then _
    ConsoleWrite("+ readbytes = " & $readbytes & @LF)
If _WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bih),DllStructGetSize($m_Bih),$readbytes) Then _
    ConsoleWrite("+ readbytes = " & $readbytes & @TAB & "biWidth = " & DllStructGetData($m_Bih,"biWidth") & @LF)
Link to comment
Share on other sites

Based on the Delphi code and the bitmap file format (http://en.wikipedia.org/wiki/BMP_file_format), you need to read the file header before you read the info header so that the file pointer will be in the correct position.

#Include <WinAPI.au3>
Global Const $tagBITMAPFILEHEADER = "ushort bfType;dword bfSize;ushort bfReserved1;ushort bfReserved2;dword bfOffBits"
Global Const $tagBITMAPINFOHEADER = "dword biSize;dword biWidth;dword biHeight;ushort biPlanes;" & _
    "ushort biBitCount;dword biCompression;dword biSizeImage;dword biXPelsPerMeter;dword biYPelsPerMeter;" & _
    "dword biClrUsed;dword biClrImportant"
    
$m_Bfh = DllStructCreate($tagBITMAPFILEHEADER)
$m_Bih = DllStructCreate($tagBITMAPINFOHEADER)
$hFile = _WinAPI_CreateFile(@ScriptDir & "\on.bmp",2,2,2)
If $hFile = 0 Then
    ConsoleWrite("! Failed to open file" & @LF)
    Exit
EndIf

Dim $readbytes
If _WinAPI_ReadFile($hFile,DllStructGetPtr($m_Bfh),DllStructGetSize($m_Bfh),$readbytes) Then _
    ConsoleWrite("+ readbytes = " & $readbytes & @LF)
If _WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bih),DllStructGetSize($m_Bih),$readbytes) Then _
    ConsoleWrite("+ readbytes = " & $readbytes & @TAB & "biWidth = " & DllStructGetData($m_Bih,"biWidth") & @LF)
Now I get that width=23265280 which is also a bit strange...

I mean the code is almost like the delphi code now, should work.

Thanks for your input though :)

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

You need to seperate the hiword and loword from the return.

ConsoleWrite(_WinAPI_HiWord(DllStructGetData($m_Bih,"biWidth")) & @CRLF)

:) I love you guys, seriously :(

Thanks so much for this, now I can finally finish my function and when I release it, well expect huge "thank to" credits :D

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

My test image is 1024x768 but the width comes back as 768 and the height is 1, anyone else?

Unfortunetly Yes, I get the same result, maybe offsetting the read position?

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Ok I managed to get the right values of biWidth and biHeight by reading one less dword from the first _WinApi_FileRead, but I don't know about the other values.

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

I believe you have to use the offset value from the file header, but I'm not sure how to use it. I've noticed that it seems to be off by just the first dword value so you could reset the file pointer like this to try and read it:

#Include <WinAPI.au3>
Global Const $tagBITMAPFILEHEADER = "ushort bfType;dword bfSize;ushort bfReserved1;ushort bfReserved2;dword bfOffBits"
Global Const $tagBITMAPINFOHEADER = "dword biSize;dword biWidth;dword biHeight;ushort biPlanes;" & _
    "ushort biBitCount;dword biCompression;dword biSizeImage;dword biXPelsPerMeter;dword biYPelsPerMeter;" & _
    "dword biClrUsed;dword biClrImportant"
    
$m_Bfh = DllStructCreate($tagBITMAPFILEHEADER)
$m_Bih = DllStructCreate($tagBITMAPINFOHEADER)
$hFile = _WinAPI_CreateFile(@ScriptDir & "\bpong.bmp",2,2,2)
If $hFile = 0 Then
    ConsoleWrite("! Failed to open file" & @LF)
    Exit
EndIf

Dim $readbytes
If _WinAPI_ReadFile($hFile,DllStructGetPtr($m_Bfh),DllStructGetSize($m_Bfh),$readbytes) Then _
    ConsoleWrite("+ readbytes = " & $readbytes & @TAB & "bfOffBits = " & _WinAPI_HiWord(DllStructGetData($m_Bfh, "bfOffBits")) & @LF)

$aResult = DllCall("kernel32.dll", "int", "SetFilePointerEx", "hwnd", $hFile, "uint64", -4, "long*", 0, "int", 1)
If $aResult[0] = 0 Then Exit

If _WinAPI_ReadFile($hFile,DllstructGetPtr($m_Bih),DllStructGetSize($m_Bih),$readbytes) Then _
    ConsoleWrite("+ readbytes = " & $readbytes & @LF)
Link to comment
Share on other sites

Thanks for all yur help in this. Really appreciate it, but this is not going to work. I have now at long long last set the format of the stream but now I have to write the bitmaps to the avi stream which means advanced file reading, buffers to data and other things I don't think I can fix.

As I said before really thanks for your help and if anyone is curious, here's the complete super messy code in which I failed :)

Also includes delphi code:

avi.au3

It's a real shame this doesn't worked out, could have created some cool stuff with it. Like a screenrecorder an such.

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...