Very big bitmap doesn't work

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Very big bitmap doesn't work

Vadim Kolontsov
Good morning, all,

    I have problems with Bitmap class. First, it doesn't allow me to
create really big image (for example, 10000x10000). It seems that
maximum size is restricted by some screen parameters (2000x2000 works
just fine). I've tried the DeviceIndependentBitmap, got same result. Am
I doing something wrong?

    Another problem is that #erase clears only a part of such big
bitmap, and this region is equal to screen resolution - I've put bitmap
into the ScrollingDecorator, so I can scroll it right and down, and I
can see big black regions (although it should be all white).

   Here is the code:

onPaintRequired: aPaintEvent
    cached ifNil: [
        cached := Bitmap compatible: self canvas
                        extent: 2000@2000.
        self extent: 2000@2000.
        cached canvas backcolor: Color white; erase.
        cached canvas pen: Pen red; brush: Brush gray;
            ellipse: (Rectangle origin: 1500@1500 extent: 100@100)].
     cached drawOn: aPaintEvent canvas.

Thanks in advance!
Vadim.


Reply | Threaded
Open this post in threaded view
|

Re: Very big bitmap doesn't work

Chris Uppal-3
Vadim Kolontsov wrote:

>     I have problems with Bitmap class. First, it doesn't allow me to
> create really big image (for example, 10000x10000). It seems that
> maximum size is restricted by some screen parameters (2000x2000 works
> just fine). I've tried the DeviceIndependentBitmap, got same result. Am
> I doing something wrong?

I don't think so.  I believe it's just a system limit (10000x10000 is 100M
pixels, each of which would require 3 (or 4?) bytes, so that's quite a big
chunk of memory).  On my machine here I can go up to 3000x4000 or 4000x3000,
but not to 4000x4000.

The easy way to avoid the problem is not to use double-buffering.  So you are
drawing directly on the view canvas in your onPaintRequired: method, which
would then look something like (untested):
    onPaintRequired: aPaintEvent
        | canvas |
        canvas := aPaintEvent canvas.
        canvas backcolor: Color white;
        ... etc

Of course, that will flicker rather, which can be annoying.  There's no easy
way around it except to use a smaller double buffer that is only large enough
to cover your actual window, but then you have to implement the scroll offsets
yourself.  I suppose that would be the best way in the long term, but it's
probably better to live with the flickering while you get the other stuff
working, and gain more experience in Dolphin/Windows graphics.  (Of course, you
could always use a double buffer if the system allocated one, falling back to
drawing directly if the picture was too big).

You'll also hit an oddity with the canvas #extent, which you will have to code
for yourself:

> Another problem is that #erase clears only a part of such big bitmap

Yes, that's one side-effect of the problem.  It turns out that Canvases that
are connected (however indirectly) to the screen all think their #extent is the
same as the screen's.  I have no idea why this should be, but it seems to be a
Windows thing.  That's why the canvas's own #erase method doesn't work for
Canvases that are bigger than the screen.  It just means that you have to keep
track of the real size yourself.  I use the owning View's #clientExtent for
this purpose.  For instance, to erase the canvas, I use code like:

    aCanvas
        fillRectangle: self clientRectangle
        brush: (aCanvas backcolor).

I'm sorry I didn't think to mention the #extent problem in my earler post --
I'd forgotten all about it.

    -- chris