The MASM Forum

General => The Workshop => Topic started by: clamicun on June 14, 2017, 01:53:15 AM

Title: Dimensions of a bitmap
Post by: clamicun on June 14, 2017, 01:53:15 AM
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.   
Title: Re: Dimensions of a bitmap
Post by: raymond on June 14, 2017, 02:15:53 AM
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.
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 14, 2017, 02:56:46 AM
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" ?
Title: Re: Dimensions of a bitmap
Post by: FORTRANS on June 14, 2017, 03:25:07 AM
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
Title: Re: Dimensions of a bitmap
Post by: raymond on June 14, 2017, 03:46:56 AM
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.
Title: Re: Dimensions of a bitmap
Post by: Vortex on June 14, 2017, 04:17:45 AM
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;
.
.
.
Title: Re: Dimensions of a bitmap
Post by: raymond on June 14, 2017, 06:13:31 AM
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.
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 14, 2017, 07:19:41 AM
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. 
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 14, 2017, 07:30:01 AM
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 ...
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 14, 2017, 08:00:48 PM
No, it is not that simple.
There are jpgs without offset FF C0.
Where to look there ?
Title: Re: Dimensions of a bitmap
Post by: TWell on June 14, 2017, 08:22:01 PM
http://www.fileformat.info/format/jpeg/egff.htm
Title: Re: Dimensions of a bitmap
Post by: jj2007 on June 14, 2017, 09:22:03 PM
Quote from: clamicun on June 14, 2017, 08:00:48 PM
There are jpgs without offset FF C0.

Can you post one?
Title: Re: Dimensions of a bitmap
Post by: TWell on June 14, 2017, 10:33:29 PM
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  .........ÿÚ.....
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 14, 2017, 11:43:23 PM
Thanks TWell,
so it is not safe to only check for FF C0
Title: Re: Dimensions of a bitmap
Post by: Vortex on June 15, 2017, 03:05:29 AM
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
Title: Re: Dimensions of a bitmap
Post by: raymond on June 15, 2017, 03:31:40 AM
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.
Title: Re: Dimensions of a bitmap
Post by: JoeBr on June 15, 2017, 06:06:37 AM
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



Title: Re: Dimensions of a bitmap
Post by: jj2007 on June 15, 2017, 07:02:44 AM
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)
Title: Re: Dimensions of a bitmap
Post by: Siekmanski on June 15, 2017, 07:42:20 AM
You have been fooled, there are only 256 colors in that frame.  :biggrin:
Title: Re: Dimensions of a bitmap
Post by: jj2007 on June 15, 2017, 07:49:21 AM
Your feedback is very precise as usual, Marinus :badgrin:
Title: Re: Dimensions of a bitmap
Post by: hutch-- on June 15, 2017, 04:47:22 PM
No problems Joe, it makes life easier when new members post as we then know they are not bots.
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 16, 2017, 04:50:30 AM
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.
Title: Re: Dimensions of a bitmap
Post by: HSE on June 16, 2017, 05:24:20 AM
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
Title: Re: Dimensions of a bitmap
Post by: Vortex on June 16, 2017, 06:18:39 AM
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
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 16, 2017, 06:34:52 AM
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
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 16, 2017, 07:28:35 AM
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 ??
Title: Re: Dimensions of a bitmap
Post by: JoeBr on June 16, 2017, 07:52:53 AM
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
Title: Re: Dimensions of a bitmap
Post by: clamicun on June 18, 2017, 01:46:19 AM
Thanks to all,
everything is ok now