News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

A useful tool: BMP data viewer

Started by NoCforMe, November 20, 2024, 06:32:00 PM

Previous topic - Next topic

NoCforMe

Quote from: zedd151 on November 22, 2024, 08:10:32 AM
Quote from: NoCforMe on November 22, 2024, 08:09:18 AMOne basic question, though, before I start revamping this code:
Do you think anyone's actually going to use all this bitmap data?
I'd hate to get this working all nice and perfect but to no practical use.

(The displayed text will be larger than the BMP file)
Personally, I would use a hex editor myself. But you never know about anyone else.

Sure, one could use a hex editor. But you'd have to work out where the BMP header ended, where the palette data was, where the bitmap data started, all that. The motivation for this was to display all that data without having to wade through the hex dump.

Maybe this tool could/should use a hex-dump format in displaying the palette and bitmap data? Maybe even allow editing? Ugh; lotsa lotsa work there.

No, I think I'll stick to read-only for this version at least. If you're going to edit a BMP, then use a graphics editor (like Paint Shop Pro here), not a stupid  hex editor.

Anyhow, I'm open to suggestions.
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: NoCforMe on November 22, 2024, 08:15:37 AMIf you're going to edit a BMP, then use a graphics editor (like Paint Shop Pro here), not a stupid  hex editor.
Well thats all  I could think of, to see the bitmap data.  :tongue:   Carry on.

sinsi

I tend to write this sort of program to work out the structure of things (like here, trying to figure out the bitmap format). Sometimes MSDN can be a bit cryptic to a non-C programmer.

For example, one of the bitmaps I tried with this program had horiz. res and vert. res set to 0, which puzzled me until I looked at the header and saw that it is measuring pixels per metre. No idea why you would want that measurement  :badgrin:
Tá fuinneoga a haon déag níos fearr :biggrin:

NoCforMe

Progress: dynamic memory allocation implemented, like it shoulda been done from the get-go.

But as always, 2 steps forward, 1 step back: now there's a fault on exit, hard to debug since it ends up somewhere in ntdll territory.

Also, the suspended wait is just too long for large BMPs. Seems like the only solution is to put all that computation into a separate thread. Next up.
Assembly language programming should be fun. That's why I do it.

NoCforMe

The compute-intensive code now runs in a worker thread, which I would have thought would solve the nonresponsiveness issue, but it hasn't. Still, this version is an improvement. Seems pretty bulletproof.

I took all the code that takes a long time to execute (displaying the palette and especially the bitmap data) and put it in a separate subroutine. I then start it thus:

;========================================
; Start worker thread to crunch BMP data:
;========================================
INVOKE CreateThread, OFFSET ThreadSecAttr, 0, OFFSET ProcessBitmapData,
NULL, 0, NULL

The thread routine ends so:

; Free buffers:
INVOKE HeapFree, HeapHandle, 0, FileBuffer
INVOKE HeapFree, HeapHandle, 0, TextBuffer

INVOKE ExitThread, 0
RET

So when you run this, you can still move the dialog window around while it's crunching away. However, you shortly get the "busy" cursor and the title says "not responding". I thought that having code execute in a separate thread would fix this; why didn't it? Nothing in the main program is waiting on the threaded subroutine to complete.

Something else I don't understand--the Micro$oft documentation for CreateThread() says

QuoteThe thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to CloseHandle.

So CreateThread() returns a handle: what am I supposed to do with it? I could close it right after the call to this function, but wouldn't that mess up the thread which is (or may be) still executing? Or should I store the handle and close it later? But when?

I guess I still have a few things to learn about Windows threads.
Assembly language programming should be fun. That's why I do it.

zedd151

It does run much faster than the original version. :thumbsup:

sinsi

BMP width: 2002
BMP height: 1505
no. planes: 1
bits/pixel: 8
bitmap size: 3016020 bytes
Still takes ages and the dialog is unresponsive.

379766016: 00 00 00 00 00 49 49 51 51 51 51 51 51 51 51 51 BMP size  =   3,016,020
info size = 379,766,016

Hmmm...
Tá fuinneoga a haon déag níos fearr :biggrin:

NoCforMe

#22
What do you mean, "info size = 379,766,016"?

The file you posted is about 9MB, which is about right; typically the text output is ~3X the size of the BMP.

There was one glaring error in the memory addresses of each line of pixels which I just fixed, but that only affects the number shown before each line. (Take a look at the output, it'll jump out atcha.)

Yeah, it's slow.

So about the thread: do I need to mess around with WaitForMultipleObjects() or WaitForSingleObject() or some such to make the program responsive while that thread is executing? I'm definitely not an expert on using threads. (I like to wear natty ones, though.)

Oh,, and another thing: looking at Task Manager while this thing's grinding away, I see memory usage steadily climbing, which I don't understand at all, because I'm not allocating any memory inside that code. So what the hell is going on there? I'm not even calling any Win32 functions there, not doing anything with any controls (like the edit control): I'm just stuffing text into a buffer.

I am using wsprintf(): could that be hogging all that memory?
No, because I'm only using that for 32bpp images.
Assembly language programming should be fun. That's why I do it.

sinsi

Quote from: NoCforMe on November 22, 2024, 05:17:56 PMWhat do you mean, "info size = 379,766,016"?
Quote from: sinsi379766016:   00 00 00 00 00 49 49 51 51 51 51 51 51 51 51 51
Quote from: NoCforMe on November 22, 2024, 05:17:56 PMThere was one glaring error in the memory addresses of each line of pixels which I just fixed, but that only affects the number shown before each line. (Take a look at the output, it'll jump out atcha.)
But not atchoo :biggrin:

You might want to sync the thread, if someone loads another bitmap before the thread is finished you might get some interesting things happening...
Tá fuinneoga a haon déag níos fearr :biggrin:

zedd151


daydreamer

You should read in filesize first and allocate memory according to that and free memory after finished
For hex editing bmp and other files,there are already qeditor binary load/save functions
I used this binary load bmp after creating and saving 'empty' bmp with paint,just to copy and paste bmp file headers into my programs that "draws" isometic 3d and saves as bmp witt same size and bitness as previous empty bmp

with lots of optimizers here that can help you


my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

NoCforMe

New version attached.

I've eliminated all wsprintf()s at least from the most compute-intensive code (the pixel-displaying stuff); I'm doing all the number conversions (decimal & hex) by myself, so it's a wee bit faster. Still sloooow on large BMPs. I don't see much room for improvement in my code.

Also corrected the address display for lines of pixels.

But there are still (at least) two things that bother me:

1. I still see memory usage slowly but steadily climbing while this runs, and I can't figure out why. I am doing absolutely no memory allocation in the pixel-display code, nor am I using any Win32 functions; it's all just code working with variables.

I wonder: if you allocate a large buffer using HeapAlloc(), is it possible that as you use more and more of the buffer, the OS is actually doing some kind of incremental allocation? I always thought that if you allocate, say, 8 MB of memory that you're given an 8 MB chunk in one fell swoop. But maybe it doesn't work that way: maybe that 8 MB is only marked out as being allocated, but as you use more and more of the buffer (by making memory references to it), it is physically allocated by page faults. I don't know enough about the innards of Windows to answer this, but it would explain the steadily increasing memory usage I'm seeing. (Calling Raymond Chen!)

2. Still don't know why the program goes non-responsive while cranking through all that data, since that code is in a separate thread now. Apparently that's not sufficient to prevent the compute-intensive code from bogging down the rest of the program. The program uses a dialog as the main window; maybe the dialog manager doesn't play well with my thread?

If anyone knows anything about either of these two things, could you reply and post what you know here? It would be much appreciated.

As it is, this is still a useful tool. And maybe that long wait is deserved: after all, anyone who makes that large a BMP is just asking for trouble ...
Assembly language programming should be fun. That's why I do it.

_japheth

Quote from: NoCforMe on Today at 10:21:06 AMIf anyone knows anything about either of these two things, could you reply and post what you know here? It would be much appreciated.

Can't do a comment on those 2 things, because the program crashes - feeding it with a very simple 16bpp bitmap (attached). I'm using WinXP 32bit, in a VM under Linux, though. Seems the crash is due to "TextBuffer" being too small...



Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

sinsi

It is a lot faster, but still not responsive.

_japheth found a BMP that's in a format rarely seen nowadays (though perfectly valid) - 16 bits per pixel, which your code doesn't allow for.
Tá fuinneoga a haon déag níos fearr :biggrin:

NoCforMe

Thanks, @_japheth: I should have that format (16bpp) handled by tomorrow.

Any clue on the non-responsiveness? I'm really starting to think that this might have something to do with the dialog manager. I was considering using IsDialogMessage(), but since I don't have a message loop that won't do much good.
Assembly language programming should be fun. That's why I do it.