BBC BASIC for Windows
« Create DIBSection moved to tool section »

Welcome Guest. Please Login or Register.
Apr 5th, 2018, 10:04pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

If you require a dump of the post on your message board, please come to the support board and request it.


Thank you Conforums members.

BBC BASIC for Windows Resources
Online BBC BASIC for Windows documentation
BBC BASIC for Windows Beginners' Tutorial
BBC BASIC Home Page
BBC BASIC on Rosetta Code
BBC BASIC discussion group
BBC BASIC for Windows Programmers' Reference

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: Create DIBSection moved to tool section  (Read 410 times)
michael
Senior Member
ImageImageImageImage


member is offline

Avatar




PM


Posts: 335
xx 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 » User IP Logged

I like making program generators and like reinventing the wheel
DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx 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%
 
User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls