Author |
Topic: Create DIBSection moved to tool section (Read 409 times) |
|
michael
Senior Member
member is offline


Posts: 335
|
 |
Create DIBSection moved to tool section
« Thread started on: Sep 19th, 2016, 12:03am » |
|
Ric I moved this in the tool section, so that is easier to find. I am going to adapt it to BMPtoCode output file and then see if it is faster. And I guess I should probably translate BMPtoCode to BBC since its awkward needing to use it in its LBB form.
Although, it doesnt hurt to just use it as it is and improve it for BBC. Code:
REM The 3rd and 4th components of the VDU 23,22 statement must be the same as bmi.Header.Width% and bmi.Header.Height%
VDU 23,22,1024;640;16,16,16,0
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = 1024
bmi.Header.Height% = 640
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 32
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
IF hbitmap%=0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
SYS "InvalidateRect", @hwnd%, 0, 0
REM The code to this point sets the screen size in pixels and creates bitmap to the same size
REM To access the bitmap you need to use bit% :-
REM Each pixel is four bytes
REM You can access one at a time with "bits%?(X,Y)=8_bit_number"
REM Or all four bytes at the same time "bits%!(X,Y)=&aaRRGGBB
REM when setting X and Y remember they are pixel coordinates not graphics coordinates
X=100
Y=100
bits%?( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = 255 : REM Will put a blue dot at 100,100
X=110
bits%!( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = &00FF00FF : REM Will put a magenta dot at 110,100
REM The reason for the "* bmi.Header.Width%" is to move the "Y" position up the screen by the correct displacement
REM and the "*4" is because each position on the bit map is four pixels
REM A simple line
FOR loop = 200 TO 400
bits%!( ( loop + ( loop * bmi.Header.Width% ) ) * 4 ) = &00FF8000
NEXT
REM After you have finished accessing the bit map a "*REFRESH" is needed to update the screen
*REFRESH
AND here is my improvements so far!!
There is a problem... Why is the line length changing at times?
Try running this program a few times... Can someone see the reason it is not always holding the same length?
Code: REM The 3rd and 4th components of the VDU 23,22 statement must be the same as bmi.Header.Width% and bmi.Header.Height%
VDU 23,22,1024;640;16,16,16,0
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = 1024
bmi.Header.Height% = 640
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 32
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
IF hbitmap%=0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
SYS "InvalidateRect", @hwnd%, 0, 0
REM The code to this point sets the screen size in pixels and creates bitmap to the same size
REM To access the bitmap you need to use bit% :-
REM Each pixel is four bytes
REM You can access one at a time with "bits%?(X,Y)=8_bit_number"
REM Or all four bytes at the same time "bits%!(X,Y)=&aaRRGGBB
REM when setting X and Y remember they are pixel coordinates not graphics coordinates
X=100
Y=100
bits%?( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = 255 : REM Will put a blue dot at 100,100
X=110
bits%!( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) =&FF0000
X=115
bits%!( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = &00FF00FF : REM Will put a magenta dot at 110,100
FOR loop = 300 TO 500
bits%!( ( loop + ( loop * bmi.Header.Width% ) ) * 4 ) = &400040 :REM DARK PURPLE
bits%!( ( loop +8+ ( loop * bmi.Header.Width% ) ) * 4 ) = &FF0000 :REM RED
bits%!( ( loop +15+ ( loop * bmi.Header.Width% ) ) * 4 ) = &F36E2D7 :REM CYAN
bits%!( ( loop +16+ ( loop * bmi.Header.Width% ) ) * 4 ) = &F36E2D7 :REM CYAN
bits%!( ( loop +25+ ( loop * bmi.Header.Width% ) ) * 4 ) = &0011E6380C :REM orange
bits%!( ( loop +35+ ( loop * bmi.Header.Width% ) ) * 4 ) = &00BEFA717 :REM yellow
bits%!( ( loop +45+ ( loop * bmi.Header.Width% ) ) * 4 ) = &00F360BFF :REM blue
bits%!( ( loop +55+ ( loop * bmi.Header.Width% ) ) * 4 ) = &00F36E23C :REM green
bits%!( ( loop +65+ ( loop * bmi.Header.Width% ) ) * 4 ) = &005F9C57C :REM TAN
bits%!( ( loop +80+ ( loop * bmi.Header.Width% ) ) * 4 ) = &65497 :REM light blue
bits%!( ( loop +90+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM Greyish purple?
bits%!( ( loop +91+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM greyish purple?
bits%!( ( loop +92+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM greyish purple?
bits%!( ( loop +93+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM greyish purple?
bits%!( ( loop +99+ ( loop * bmi.Header.Width% ) ) * 4 ) = &6549 :REM grass green
bits%!( ( loop +109+ ( loop * bmi.Header.Width% ) ) * 4 ) = &65 :REM ? dark blue
bits%!( ( loop +129+ ( loop * bmi.Header.Width% ) ) * 4 ) = &12632256:REM purple
bits%!( ( loop +149+ ( loop * bmi.Header.Width% ) ) * 4 ) = &167777215 :REM Dark yellow
bits%!( ( loop +159+ ( loop * bmi.Header.Width% ) ) * 4 ) = &167777:REM dark cyan
bits%!( ( loop +169+ ( loop * bmi.Header.Width% ) ) * 4 ) = &167772111:REM dark red
bits%!( ( loop +179+ ( loop * bmi.Header.Width% ) ) * 4 ) = &FFFFFF: REM BRIGHT WHITE BMPtoCODE
bits%!( ( loop +189+ ( loop * bmi.Header.Width% ) ) * 4 ) = &C0CFD0: REM GRAY? BMPtoCODE
bits%!( ( loop +199+ ( loop * bmi.Header.Width% ) ) * 4 ) = &C0C0C0: REM Light GRAY BMPtoCODE
bits%!( ( loop +209+ ( loop * bmi.Header.Width% ) ) * 4 ) = &A0013BF: REM RED BMPtocode? NOPE!! its blue
NEXT
bits%!( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = &400040 :REM DARK PURPLE
REM The reason for the "* bmi.Header.Width%" is to move the "Y" position up the screen by the correct displacement
REM and the "*4" is because each position on the bit map is four pixels
REM A simple line
REM After you have finished accessing the bit map a "*REFRESH" is needed to update the screen
*REFRESH
|
« Last Edit: Sep 20th, 2016, 03:26am by michael » |
Logged
|
I like making program generators and like reinventing the wheel
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Create DIBSection moved to tool section
« Reply #1 on: Sep 22nd, 2016, 08:52am » |
|
Hi Michael,
I know you got the answer from Richard on the other forum, but for any who don't also read there:
When you write to a bitmap directly like this, you need to tell Windows to update it. The command is:
SYS "InvalidateRect",@hwnd%,0,0
That will tell Windows to repaint the whole output window: if you are interested in speed you might prefer to give a Rect{} structure in place of the first 0, telling Windows which region has changed. Using *REFRESH will NOT have quite the same effect, though I don't know why. Richard, if you are reading and want to tell me, I'll post it!
Just to clarify, my understanding is that 1) changing to a DIBSection in itself will not make anything happen faster (or slower, as far as I know). 2) You can still use the built-in BB4W graphics commands for lines, shapes, etc. These will almost certainly be MUCH faster than you can achieve by writing your own routines to plot them pixel-by-pixel, unless you do it in assembler. 3) The one case where it IS faster is if you are setting a lot of points individually, in which case direct memory writes will be quite a bit faster than using PLOT.
To demonstrate this, here's a short program to plot a filled rectangle 200 pixels square. On my machine, using PLOT 69 takes about 30 centiseconds, direct memory writes takes about 1-2 centiseconds, and using RECTANGLE FILL consistently returns 0!
Best wishes,
D
Code:
REM The 3rd and 4th components of the VDU 23,22 statement must be the same as bmi.Header.Width% and bmi.Header.Height%
VDU 23,22,1024;640;16,16,16,0
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = 1024
bmi.Header.Height% = 640
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 32
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
IF hbitmap%=0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
offset%=400*bmi.Header.Width%+1600 :REM Move up 100 pixels and across 400 pixels, times 4 bytes
REM LEt's draw it a point at a time, using PLOT
*REFRESH OFF
TIME=0
GCOL 15
FOR y%=0 TO 199
FOR x%=0 TO 199
PLOT 69,2*x%+200,2*y%+200
NEXT x%
NEXT y%
*REFRESH ON
time1%=TIME
REM Now we'll draw it a point at a time, using direct writes to the DIBSection
TIME=0
FOR y%=0 TO 199
FOR x%=0 TO 199
bits%!(offset%+x%*4)=&00FF0000
NEXT x%
offset%+=bmi.Header.Width%*4
NEXT y%
SYS "InvalidateRect",@hwnd%,0,0
time2%=TIME
REM Finally we'll use RECTANGLE FILL
TIME=0
GCOL 4
RECTANGLE FILL 1400,200,400,400
time3%=TIME
PRINT time1%,time2%,time3%
|
|
Logged
|
|
|
|
|