Bitmaps from ByteArrays

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

Bitmaps from ByteArrays

Günther Schmidt
Hi Blair,

I'd like to follow up on creating Bitmaps (and Icons) from ByteArrays.

How would I do that?

Günther


Reply | Threaded
Open this post in threaded view
|

Re: Bitmaps from ByteArrays

Udo Schneider
Günther Schmidt wrote:
> I'd like to follow up on creating Bitmaps (and Icons) from ByteArrays.
I'm not sure about Bitmaps and Icons ... but something similar can be
done with OLEPictures. Take a look here:
http://groups.google.com/group/comp.lang.smalltalk.dolphin/browse_frm/thread/7f33c877af3094a4/246bf8ddf7131cde?q=OLEPicture+fromByteArray:&rnum=1#246bf8ddf7131cde

CU,

Udo


Reply | Threaded
Open this post in threaded view
|

Re: Bitmaps from ByteArrays

Chris Uppal-3
In reply to this post by Günther Schmidt
Günther,

> I'd like to follow up on creating Bitmaps (and Icons) from ByteArrays.

Icons are complicated since they consist of several images.  Bitmaps are less
complicated, but since there are many possible formats, there is a fair amount
to consider, and to get wrong.

If you want to keep it simple, then a good way is just to write the ByteArray
to a temporary .BMP or .ICO file, and then load that in the normal way.

Otherwise, the following may help get you started on manipulating image data
directly.  But please note the following warnings:

a) there are several possible image formats, with correspondingly different
pixel layouts in memory.  See Petzold for guidance.

b) doing this kind of thing can totally trash your image, and not necessarily
in ways that will show up immediately, since you are writing to arbitrary
memory locations.  (in fact I discaded the image I used to write this demo
code -- I didn't trust myself to have got it right).

Anyway.

To create sample bitmap.  We'll start with a "DIB section" (silly Windows
terminology) that is 11x7 and 24 bits deep.  Note that we're working with odd
numbers to help show up where rounding-up happens:

    dibs := DIBSection width: 11 height: 7 depth: 24.

Get a view of it.  This will be automatically stretched, which is handy since
we are using a very small image:

    v := (ImagePresenter showOn: dibs) view.

Now get some important information about the bitmap's size and shape in memory:

    info := dibs getInfo.
    bytesPerPixel := info bmBitsPixel / 8.
    bytesPerRow := info bmWidthBytes. "note that this is rounded up"
    totalSize := bytesPerRow * info bmHeight.

Now get the address where the actual binary data is stored:

    addr := dibs imageBits.

Copy that data into a ByteArray (actually the data is pretty dull since it
starts off all zero):

    copyBytes := ByteArray fromAddress: addr length: totalSize.

Change the copy to all ones (for white):

    copyBytes atAllPut: 16rFF.

Copy the changed data back to the image, and #invalidate the view, so we
will see the effect immediately:

    addr
        replaceFrom: 1
        to: copyBytes size
        with: copyBytes
        startingAt: 1.
    v invalidate.

Or instead we can scribble directly onto the binary data.  This stuff is pretty
tricky to get right; it helps if you take as few short-cuts as possible.  This
code will draw a black X on the bitmap:

    "draw one bar"
    0 to: info bmHeight-1 do:
        [:i || x y offset |
        x := i.
        y := i.
        offset := (y * bytesPerRow) + (x * bytesPerPixel).
        0 to: bytesPerPixel-1 do:
            [:b |
            "safety!"
            self assert: [offset+b < totalSize].
            addr byteAtOffset: offset+b put: 0]].

    "draw the other bar, the only difference is the value of y in the loop"
    0 to: info bmHeight-1 do:
        [:i || x y offset |
        x := i.
        y := info bmHeight - 1 - i.
        offset := (y * bytesPerRow) + (x * bytesPerPixel).
        0 to: bytesPerPixel-1 do:
            [:b |
            "safety!"
            self assert: [offset+b < totalSize].
            addr byteAtOffset: offset+b put: 0]].

    v invalidate.

On the whole, I think it's probably better (safer) do all the difficult work in
ByteArrays that are copies of the image data, and have only one or two very
well-tested methods for transfering data between the real image and the copy.

I'm afraid I have no idea how to play similar tricks with icons -- as I said,
they are more complicated beasts.  Some time ago Diego posted a link to a small
package by Hernan Galante that could create single-image Icons from bitmaps.
It used to be at:
    http://www.smalltalking.net/Goodies/Dolphin/
but doesn't seem to be on that page any longer (the stuff there is still worth
looking at, though!).  I can send you a copy if you like.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Bitmaps from ByteArrays

Günther Schmidt
Chris,

thanks.

See the basic idea behind this is to be able to store the icons in a
byte array in a method.

And the idea behind that is so that we all can do without having to
create separate icon or resource files when we deploy the application.

I'll give it some more tries.

Günther