To get the width and height of a bitmap ..
;============================
INVOKE MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,offset image_path,-1,ADDR UnicodeFileName,MAX_PATH-1
INVOKE GdipCreateBitmapFromFile,ADDR UnicodeFileName,ADDR BmpImage
INVOKE GdipCreateHBITMAPFromBitmap,BmpImage,ADDR hBitmap,0
INVOKE CreateCompatibleDC,0
mov hMemDC,eax
INVOKE SelectObject,hMemDC,hBitmap
INVOKE GetObject,hBitmap,sizeof(BITMAP),ADDR bm
lea edx,bm
mov eax,BITMAP.bmWidth[edx]
mov image_width,eax
mov eax,BITMAP.bmHeight[edx]
mov image_height,eax
INVOKE DeleteDC,hMemDC
;===========================
Is there a "simpler" function to get the dimension ?
If I upload a whole directory of fotos (jpgs) into a database it slows down my proc and on "special ocasions ?" (weekdays, humour of my machine, weather a.o. might bring it down.
If you only need to know the dimensions of the image, why don't you simply extract it from the 'header' of the file itself instead of going to all the trouble of loading the file, decompressing it, loading it into a compatible DC, and then getting that same data from the DC.
That is my intention.
To get other filedata I do this...
INVOKE CreateFile,offset image_path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0 ;filename öffnen
mov filehandle,eax
INVOKE GetFileInformationByHandle,filehandle,addr BHFI
mov eax, BHFI.nFileSizeLow
mov image_size,eax
and more.
BHFI doesn't give me the dimensions.
What do you mean with "Fileheader" ?
Hi,
Quote from: clamicun on June 14, 2017, 02:56:46 AM
What do you mean with "Fileheader" ?
Image files like *.BMP or *.GIF start with information that
describes how to decode the image. Width, height, and number
of colors are typically part of a structure in the first part of the
file. And this is called the header of the image file.
HTH,
Steve
And, each file type will have its own structure for the information. Once you understand those structures, you can easily extract whatever info you need.
Hi clamicun,
Here is an example :
.IF uMsg==WM_CREATE
invoke ReadFileToMem,ADDR filename,ADDR pBitmap,\
ADDR pNumbOfBytesRead
invoke CreateBmpFromMem,hWnd,pBitmap,ADDR hDC1
mov hBitmap,eax
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd,ADDR ps
mov hdc,eax
invoke CreateCompatibleDC,eax
mov hMemDC,eax
invoke SelectObject,eax,hBitmap
mov ecx,pBitmap
lea edx,[ecx+sizeof(BITMAPFILEHEADER)] ; start of the BITMAPINFOHEADER header
xor eax,eax
invoke BitBlt,hdc,eax,eax,\
BITMAPINFOHEADER.biWidth[edx],\
BITMAPINFOHEADER.biHeight[edx],\
hMemDC,eax,eax,SRCCOPY
invoke DeleteDC,hMemDC
invoke EndPaint,hWnd,ADDR ps
pBitmap is the pointer to the bitmap loaded to memory. The structure BITMAPINFOHEADER is what you are looking for :
typedef struct tagBITMAPINFOHEADER {
.
.
.
LONG biWidth;
LONG biHeight;
.
.
.
If you look at the header of a JPG file with a hex viewer, the first two bytes you should see (in hex format) are FF D8. If you continue to look at the header, you will notice more FF bytes followed by another byte (such as E0, DB, ...) which would be specific to describe the type of the subsequent data.The two following bytes (in bigendian format) would indicate the length of that data (including its size). The area where the FF is followed by C0 is where the dimensions of the image are located. The height (again in bigendien format) would be in the 4th and 5th bytes following the C0, while the width would be in the 6th and 7th bytes.
Have fun. The headers of other image file types (such as GIF, BMP, ...) would be entirely different.
Thank you all, especially Ramond,
After I asked what you mean with header I started to check it out.
Think I understood.
I tested various jpgs and found height and width after offset FF C0 in the file.
Vortex, your eaxample.
that is exactely what I did.
And like Raymond explained, it's much faster to read the header. I have to open the file anyway for "GetFileInformationByHandle" ... And even that might be unnecessary ... ? maybe all information is in the header ...
No, it is not that simple.
There are jpgs without offset FF C0.
Where to look there ?
http://www.fileformat.info/format/jpeg/egff.htm
Quote from: clamicun on June 14, 2017, 08:00:48 PM
There are jpgs without offset FF C0.
Can you post one?
https://en.wikipedia.org/wiki/JPEG
QuoteSOF2 0xFF, 0xC2 variable size Start Of Frame (progressive DCT) Indicates that this is a progressive DCT-based JPEG, and specifies the width, height, number of components, and component subsampling (e.g., 4:2:0).
00000090 ff c2 ÿÂ
000000a0 00 11 08 02 ad 01 d4 03 01 22 00 02 11 01 03 11 .....Ô.."......
000000b0 01 .
00000000 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 ÿØÿà..JFIF......
00000010 00 01 00 00 ff db 00 43 00 0a 07 07 08 07 06 0a ....ÿÛ.C........
00000020 08 08 08 0b 0a 0a 0b 0e 18 10 0e 0d 0d 0e 1d 15 ................
00000030 16 11 18 23 1f 25 24 22 1f 22 21 26 2b 37 2f 26 ...#.%$"."!&+7/&
00000040 29 34 29 21 22 30 41 31 34 39 3b 3e 3e 3e 25 2e )4)!"0A149;>>>%.
00000050 44 49 43 3c 48 37 3d 3e 3b ff db 00 43 01 0a 0b DIC<H7=>;ÿÛ.C...
00000060 0b 0e 0d 0e 1c 10 10 1c 3b 28 22 28 3b 3b 3b 3b ........;("(;;;;
00000070 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b ;;;;;;;;;;;;;;;;
00000080 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b ;;;;;;;;;;;;;;;;
00000090 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b ff c2 ;;;;;;;;;;;;;;ÿÂ
000000a0 00 11 08 02 ad 01 d4 03 01 22 00 02 11 01 03 11 .....Ô.."......
000000b0 01 ff c4 00 1b 00 00 02 03 01 01 01 00 00 00 00 .ÿÄ.............
000000c0 00 00 00 00 00 00 00 01 02 03 04 05 06 07 ff c4 ..............ÿÄ
000000d0 00 19 01 01 01 01 01 01 01 00 00 00 00 00 00 00 ................
000000e0 00 00 00 00 01 02 03 04 05 ff da 00 0c 03 01 00 .........ÿÚ.....
Thanks TWell,
so it is not safe to only check for FF C0
Quote from: clamicun on June 14, 2017, 07:30:01 AM
Vortex, your eaxample.
that is exactely what I did.
No, not exactly the same.
Quote
And like Raymond explained, it's much faster to read the header. I have to open the file anyway for "GetFileInformationByHandle" ... And even that might be unnecessary ... ? maybe all information is in the header ...
My example above follows Raymond's method. You don't need the API GetFileInformationByHandle. Maybe, my example was not clear. Another example :
include GetBmpSize.inc
.data
msg1 db 'Usage : GetBmpSize.exe bitmapfile.bmp',13,10,0
msg2 db 'Width = %u',13,10
db 'Height = %u',0
.data?
buffer1 db 512 dup(?)
buffer2 db 512 dup(?)
.code
start:
call main
invoke ExitProcess,0
main PROC uses esi
LOCAL pMem:DWORD
LOCAL BytesRead:DWORD
mov esi,OFFSET buffer1
invoke ParseCmdLine,esi
cmp eax,1+1
je @f
invoke StdOut,ADDR msg1
ret
@@:
lea ecx,BytesRead
invoke ReadFileToMem,DWORD PTR [esi+4],
ADDR pMem,ecx
mov eax,pMem
add eax,sizeof(BITMAPFILEHEADER)
invoke wsprintf,ADDR buffer2,ADDR msg2,\
BITMAPINFOHEADER.biWidth[eax],
BITMAPINFOHEADER.biHeight[eax]
invoke StdOut,ADDR buffer2
invoke VirtualFree,pMem,0,MEM_RELEASE
ret
main ENDP
END start
Testing the application :
GetBmpSize.exe Test.bmp
Width = 119
Height = 82
Quote
Bitmap-File Structures
Each bitmap file contains a bitmap-file header, a bitmap-information header,
a color table, and an array of bytes that defines the bitmap bits. The file
has the following form:
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
RGBQUAD aColors[];
BYTE aBitmapBits[];
The bitmap-file header contains information about the type, size, and layout
of a device-independent bitmap file. The header is defined as a
BITMAPFILEHEADER structure.
The bitmap-information header, defined as a BITMAPINFOHEADER structure,
specifies the dimensions, compression type, and color format for the bitmap.
http://www.martinreddy.net/gfx/2d/BMP.txt
Quoteso it is not safe to only check for FF C0
Agree,
in the context of JPEG files. If you looked at the wiki reference (obviously faster than trying to digest the entire jpeg specification), there are two major jpeg variants, 'base line' and 'progressive'.
The latter variant is for specific purposes and rarely used. In that case, the dimensions would be located in a block marked as FF C2.
If you are interesred in GIF images, a quick description of its format can also be found on Wikipedia at https://en.wikipedia.org/wiki/GIF#File_format.
Hey there - just signed up. I've been working with Assembler (mainly masm in the beginning, and later 64-bit with HJWasm and now Uasm). Most assembly for me has been dealing with GDI and GDI-Plus. General background is database programming in various languages, a LITTLE C and C++/C-Sharp, and VB.Net. My apologies if this isn't in the right place for a 'New Member Posting' - looking around and couldn't see a New Member Posting area - again sorry if I missed it.
So far as the dimensions and a more 'general approach' - maybe something like -
invoke MultiByteToWideChar, CP_ACP,0, psPath,-1, addr sPathWide, 128
invoke GdipCreateBitmapFromFile,addr sPathWide, addr hbmp
...
invoke GdipGetImageWidth,hbmp,pdSrcW
invoke GdipGetImageHeight,hbmp,pdSrcH
?
(This is the basic I've come up with in all my coding - and as I understand it GdipCreateBitmapFromFile will work with multiple image formats)
And thank you all for all of the help I've vicariously gleaned from the forum.
HTH
Joe
Here is another one, works with most image formats including animated GIFs:include \masm32\MasmBasic\Res\MbGui.asm
Event Paint
GuiImage CL$(), fit ; drag an image over the exe
GuiTextBox 100.0-99, 9, 90, 32, Cat$(Str$("Original size is %ix", GdiSI.jjWidth)+Str$(GdiSI.jjHeight))
GuiEnd
Displays the image and, in the upper right corner, a text box showing its original dimensions. Attached an example, including a beautiful Japanese image ;-)
@Joe: Welcome :icon14:
Btw there are some situations where GdipCreateBitmapFromStream is the better choice.
P.S.: Hutch will kill me for wasting server space, but check the second attachment: A 1859 colours animated GIF file 8)
You have been fooled, there are only 256 colors in that frame. :biggrin:
Your feedback is very precise as usual, Marinus :badgrin:
No problems Joe, it makes life easier when new members post as we then know they are not bots.
Fortrans,
I do not understand the readfile proc
DWORD PTR [esp+4] until DWORD PTR [esp+48] might be very professional, but names are certainly more understandable.
Anyway, it seems that the program only works with .bmp and I am only interested in .jpgs
Thank you for your work.
Hi Clamicum!
You are losing your mind with that crazy bitmaps :biggrin:
ReadFile.asm it's from Vortex!
I'm making some easy program with images, but BMP. Very soon. :t
Hi clamicun,
The ReadFileToMem function has no stack frame and this is why it looks complicated. JoeBr's suggestion is nice as you can use GDI+ to get the required information :
include GetImageSize.inc
.data
msg1 db 'Usage : GetImageSize.exe imagefile.ext',13,10,0
msg2 db 'Width = %u',13,10
db 'Height = %u',0
.data?
hBitmap dd ?
BmpImage dd ?
token dd ?
ImgWidth dd ?
ImgHeight dd ?
buffer1 db 1024 dup(?)
buffer2 db 32 dup(?)
StartupInfo GdiplusStartupInput <?>
.code
start:
call main
invoke ExitProcess,0
main PROC uses esi
mov esi,OFFSET buffer1
invoke ParseCmdLineW,esi
cmp eax,1+1
je @f
invoke StdOut,ADDR msg1
ret
@@:
mov eax,OFFSET StartupInfo
mov GdiplusStartupInput.GdiplusVersion[eax],1
invoke GdiplusStartup,ADDR token,ADDR StartupInfo,0
invoke GdipCreateBitmapFromFile,DWORD PTR [esi+4],\
ADDR BmpImage
invoke GdipGetImageWidth,BmpImage,ADDR ImgWidth
invoke GdipGetImageHeight,BmpImage,ADDR ImgHeight
invoke wsprintf,ADDR buffer2,ADDR msg2,ImgWidth,\
ImgHeight
invoke StdOut,ADDR buffer2
invoke GdipDisposeImage,BmpImage
invoke GdiplusShutdown,token
ret
main ENDP
END start
GetImageSize.exe Test.JPG
Width = 116
Height = 80
The tool can read information from .gif and .tif images. The advantage of the GDI+ method is that you don't need to know anything about the image format.
Hi JoeBr,
Thanks for your idea and welcome to the forum :t
Vortex,
excuse me for confusing names.
Yes, seems to be the easiest method to get height and width.
Thank you
Not too different from my first idea...
INVOKE MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,offset image_path,-1,ADDR UnicodeFileName,MAX_PATH-1
INVOKE GdipCreateBitmapFromFile,ADDR UnicodeFileName,ADDR BmpImage
INVOKE GdipCreateHBITMAPFromBitmap,BmpImage,ADDR hBitmap,0
INVOKE CreateCompatibleDC,0
mov hMemDC,eax
INVOKE SelectObject,hMemDC,hBitmap
INVOKE GetObject,hBitmap,sizeof(BITMAP),ADDR bm
lea edx,bm
mov eax,BITMAP.bmWidth[edx]
mov image_width,eax
mov eax,BITMAP.bmHeight[edx]
mov image_height,eax
------
but simpler
Vortex,
finally..
I would understand the program without the "parse proc"... (absolutely ununderstandable) ... not one comment.
My program reads the jpg filename out of an array.
So I need names.
invoke GdipCreateBitmapFromFile,DWORD PTR [esi+4],ADDR BmpImage
changed to
invoke GdipCreateBitmapFromFile,offset file_name,ADDR BmpImage
does not do it ??
Thanks Hutch, JJ, Vortex, and everyone. Been reading the forum for 2 or 3 years, first-time posting (just learning via personal projects and reading for a while now... now (maybe?) to the point of actually being able to help, albeit I'm still quite the noob compared to you guys). Coming from VB.Net, had to suffer for maybe a couple of weeks trying to understand the elementary(?) level of control going into assembly, that I think for me was the worst part (then it kinda just 'clicked' one day). And 64, more fun there.... and then the convention finally sunk in. This forum is quite the resource for those interested in the POWER of it all, amazing at the speed with the AVX etc ops, and the level of control in Assembler. And so many ways to write the same piece of code.
Thanks again :t
Joe
Thanks to all,
everything is ok now