Memory problems, I think...

Memory problems, I think...

Post by YYZ » Thu, 30 Sep 2004 01:23:38


Okay, let me start with what I'm trying to do, and below is how I'm trying to do
it (but open to other ideas...this is just how the project has evolved to this
point.) I am opening images off of the harddrive -- these are floorplans. They
can be rather large. Interesting to know that a .tif file that is only 813kb
can be opened by a LEAD Control or by another image viewer and it's reported
size is approx 15000x10000. Big. Anyway, after I get this .tif file loaded
(via a LEAD control), I now know the width and height of the image. What I want
to do is to create another bitmap DC in memory that has a bitmap the same size,
and I'll draw various things onto this. It's normally outlining walls on the
floorplan. I then create a 2nd bitmapDC/bitmap in memory, and I immediately
blit in the source bitmap from the lead control. Works great, but because the
.tif image is 1 color, as far as I can tell, I have to convert my bitmaps to 16
bit color (I guess it doesn'thave to be 16 bit...but I want to be able to do let
the user choose many different colors on screen for outlining the
walls/areas/etc).

That's the problem. Now here's how I've been attempting (so close!) to solve
it.

I open up the tif in the LEAD Control. I create a memory DC for the drawing
layer. I create a temporary compatible bitmap using that DC and I use the width
and height of the source image. I then use Mike D's Copy Bitmap module
( http://www.yqcomputer.com/ ) to copy
that temp bitmap to yet another bitmap, this time converting the bit depth to 16
bits. Then I delete the temp bitmap, and finally select the new bitmap into the
DC. The new bitmap and new DC have long values that are <> 0, so I'm assuming
that it works (and it looks like it does because I'm able to blit this one to
the screen after working on it and it displays correctly.

I then do the exact same process again for a 2nd memory DC and bitmap. It
doesn't work here.
lDC1 = CreateCompatibleDC(0&)
lTemp = CreateCompatibleBitmap(lDC1, lwidth, lheight)
lBM1 = Copybitmap(lTemp, cbmDIB, lwidth, lheight, 16) '<---
this is the line that it fails on. No errors, just lBM1 afte this line is 0,
which is bad.
DeleteObject lTemp
lBM1OLD = SelectObject(lDC1, lBM1)

Is this a memory problem? just not enough available? If anyone cares, I've
traced through Mike's CopyBitmap function and this line: "hDstBMP =
CreateDIBSection(hDstDC, DIBInf, DIB_RGB_COLORS, 0&, 0&, 0&)" on line 145 of
this file: http://www.yqcomputer.com/
is the one that I think fails. The 2nd time. The reason I think it fails is
because hDstBMP is 0 after this line instead of a handle to a valid
bitmap/DIBSection or whatever.

So, am I just trying to do too much in memory? Is there an alternate method I
should use? Am I doing something incredibly wrong with Mike's Code?

Any and all advice appreciated.

Matt
 
 
 

Memory problems, I think...

Post by Mike D Sut » Thu, 30 Sep 2004 18:17:25

> Okay, let me start with what I'm trying to do, and below is how I'm trying to do
<snip>

It sounds to me like you're probably reaching the GDI limitations of the system, see what Err.LastDLLError gives you after the
second CreateDIBSection() call fails.
To be honest though it sounds to me like you'd be far better off working with EMF's or vector based solutions rather than having all
these huge images floating about in memory (15000*10000*16-bit = ~286mb!!)
Also it's quite possible to display any colour you want in a 1-bpp Bitmap, simply adjust the palette either when you create it or
with the SetDIBColorTable() API call if you're using my DIB creation code - you don't need to use a full 16-bit image for that
(unless you're displaying a lot of colours simultaneously in which case a 4-bpp DIB will give you up to 16 colours and an 8-bit DIB
will give you 256 colours.)
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/

 
 
 

Memory problems, I think...

Post by YYZ » Thu, 30 Sep 2004 23:42:15


to do
this
They
813kb
want
size,
the
the
16
let
system, see what Err.LastDLLError gives you after the

I will. But I'm sure you're right. It works fine on smaller images, and I
can't setup the test for larger images for a few hours yet today.

EMF's or vector based solutions rather than having all

Yup. I may decide to take the afternoon and play with that. I remember Alpine
telling me that I should be using EMF files. I'm just so damn new to all of
this that I don't know where to start with EMF files, and I have a deadline
(arbitrarily chosen by management, of course) of having this project done by
11/1. I think I've done a pretty good job of wrapping the functionality into
hopefully easily replaced blocks if I find out how to do EMFs.

simply adjust the palette either when you create it or
you don't need to use a full 16-bit image for that
4-bpp DIB will give you up to 16 colours and an 8-bit DIB

I probably will switch to 8 BPP. That should bring cut the memory usage in
half, and they really SHOULDN'T need more than that...


As always it does. Thanks again.

Matt
 
 
 

Memory problems, I think...

Post by Mike D Sut » Fri, 01 Oct 2004 00:24:42

> Yup. I may decide to take the afternoon and play with that. I remember Alpine

If you can use PolyLine(), MoveToEx()/LineTo() etc then you can use EMF's, there's really nothing to them! My APIDraw library will
work just fine on an EMF DC so you don't even need to worry about that.
To create your EMF, simply call the Crea *** hMetaFile() API call that will return you a MetaDC which you can draw to in exactly the
same way as a memory DC with a DIBSection (or DDB) selected into it. Once you've drawn all your vector overlays into that DC you
close it using the CloseEnhMetaFile() API call (slightly oddly named since it closes a MetaDC rather than a MetaFile) which returns
you an EMF handle. The EMF can be drawn using the PlayEnhMetaFile() API call into exactly the same coordinates as your background
image area to get the alignment correct - that's it.
Once you've finished with your EMF you use the Dele *** hMetaFile() API call which reclaims the resources in the same way as
DeleteDC()/DeleteObject() would with a DC/DIBSection.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/
 
 
 

Memory problems, I think...

Post by YYZ » Fri, 01 Oct 2004 01:13:57

I have a few more questions if you have the time...



there's really nothing to them! My APIDraw library will

Good, because I'm using it extensively. <g> And for ChromaBlt (yup, got that
one from you, too) I don't think I'll need it...not quite sure yet, still trying
to work it out in my head.

return you a MetaDC which you can draw to in exactly the
you've drawn all your vector overlays into that DC you
closes a MetaDC rather than a MetaFile) which returns
into exactly the same coordinates as your background
which reclaims the resources in the same way as

So, what I'd do in my situation is this:

First, I'd load the awkwardly large .tif file using the lead control just like I
do now.

I'd then create an enhanced metafile with the same dimensions as the source
image (now as a bitmap held in memory by the lead control...I dont' have any
control over that.).

From there, I can draw rectangles, circles, etc. into the .emf file. This is
where I lose it. I understand that I'll have a DC and it will be used in the
same way that I'm using a bitmap DC right now, by drawing using api calls that
take a DC as an argument, but is this where it is going to take up less memory?
So, creating a bitmap in memory that is 15000x10000 pixels takes up more memory
than an .emf that uses the same width and height?

Assuming the above, when I goto draw on screen what the user wants to see (just
a small rectangle out of both images) I'll already have a small (same size as
picturebox on screen) DC and bitmap in memory.

I then stretchblt (taking into account zoom factors) from the leadcontrol (ie,
the source floorplan image) to the small memory DC,

Then stretchblt out of my EMF file the same dimensions (at which time I guess
the EMF actually, what's the word, "realizes" the drawing instructions I've
given it, hopefully only the ones that need to be realized, onto the same small
memory DC.

Once I have that, then I BitBlt from the small memory DC to the picturebox on
screen.

And this all happens really really fast. I'm sure it does because I'm able to
do this same type of situation with regular old memory bitmaps and DCs, and
there isn't any slowness. It just crashes trying to CREATE the bitmaps in the
first place. <g>

Anyway, if you have time to give me a nod or a smack I'd love to take them both.

Matt
 
 
 

Memory problems, I think...

Post by Mike D Sut » Fri, 01 Oct 2004 04:08:04

gt; Good, because I'm using it extensively. <g> And for ChromaBlt (yup, got that

Nope, from what you've described you shouldn't need it in this situation.


Remember that when you draw to a normal DC, you're not actually drawing to the DC itself (it's merely a container) but to the Bitmap
that's selected within it. In the same way when you draw to a MetaDC you draw to it's internal EMF which is nothing more than a
list of API drawing commands that have been fired at it.
Since your EMF simply records the drawing calls rather than actually rasterising them, creating EMF's is _very_ fast with very
little overhead since you don't require any kind of drawing surface (Bitmap) or have to rasterise the shapes as you draw them.


You can't draw only a segment of an EMF to a DC in the same way as Bit/StretchBlt() allows you to specify a source rectangle,
however GDI clipping will simply not draw anything that lies outside the visible area of the control. Rendering is a little slower
because the vector shapes have to be rasterised every time rather than just being drawn from a back-buffer as with your current
solution but it shouldn't be a problem unless you're using a very large number of shapes.


Yup, performing your drawing on a memory DC is a must with EMF's since they will flicker horribly as each shape is drawn if going
straight to the screen.


*Fingers crossed* Nah, you shouldn't have any problems with it :)


Hopefully the above is what you were after, once you've made the conceptual leap of realising that a MetaDC is really nothing more
special than a standard memory DC it should all fit into place and you'll wonder what the problem was!
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: Http://EDais.mvps.org/


 
 
 

Memory problems, I think...

Post by YYZ » Fri, 01 Oct 2004 05:05:21


DC itself (it's merely a container) but to the Bitmap
to it's internal EMF which is nothing more than a

I never really grasped that concept but when I read what you wrote, it
crystalized in my mind. Thanks for that.

rasterising them, creating EMF's is _very_ fast with very
or have to rasterise the shapes as you draw them.

I think I finally get it. I honestly believe that, thanks to you, I've made a
quantum leap on this stuff.

(just
as
(ie,
guess
small
Bit/StretchBlt() allows you to specify a source rectangle,
visible area of the control. Rendering is a little slower
being drawn from a back-buffer as with your current
of shapes.

We very well might be drawing a large number of shapes, but what I was thinking
is that I'd make an emf file for every one of our objects that we need to draw,
then figuring out which ones need to be drawn on screen at that particular time
and only drawing those into my memory resident very small DC.

on
will flicker horribly as each shape is drawn if going

Thanks for that. Hopefully I'll be able to figure out a good compromise for
speed.

leap of realising that a MetaDC is really nothing more
wonder what the problem was!

Mission accomplished. Thanks again.

Matt
 
 
 

Memory problems, I think...

Post by Mike D Sut » Fri, 01 Oct 2004 07:02:40

> I never really grasped that concept but when I read what you wrote, it
<snip>

You're welcome - see told you there was nothing to it :)


Sounds like you've cracked it to me! Bryan (Alpine) will be pleased that we now have another EMF convert *g*


It's doubtful you'll have any noticeable speed problems, especially if you're performing your own clipping of individual EMF
elements (definitely the right way to go if you've got the time to implement it.)
Cheers,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/