BBC BASIC for Windows
Programming >> Graphics and Games >> GFXLIB2: ChangeBitmapRGBLevels
http://bb4w.conforums.com/index.cgi?board=graphics&action=display&num=1318567611

GFXLIB2: ChangeBitmapRGBLevels
Post by David Williams on Oct 14th, 2011, 04:46am

I bet I end up re-naming this new routine.

http://www.bb4wgames.com/misc/chgbmrgblevels_ex1.zip (EXE; 161 Kb)

Example/demo 2 has the colours nicely subdued by GFXLIB_MMXDesaturateColour
http://www.bb4wgames.com/misc/chgbmrgblevels_ex2.zip (EXE; 162 Kb)

Playing around with the colour table...
http://www.bb4wgames.com/misc/chgbmrgblevels_ex3.zip (EXE; 164 Kb)

More silliness...
http://www.bb4wgames.com/misc/chgbmrgblevels_ex5.zip (EXE; 184 Kb)


Amazing what a few assembly language instructions can achieve.




Code below for those who might be interested.


Regards,

David.


EDIT: A swirly plasma
http://www.bb4wgames.com/misc/chgbmrgblevels_ex6.zip (EXE; 101 Kb)

And with the colours calmed down a bit...
http://www.bb4wgames.com/misc/chgbmrgblevels_ex6b.zip (EXE; 101 Kb)


=====================================

GFXLIB_ChangeBitmapRGBLevels

Code:
      DEF PROCInitModule
      PROCInitModule( 0 )
      ENDPROC
      
      DEF PROCInitModule( V% )
      LOCAL codeSize%, I%, L%, P%, _{}, M$
      
      M$ = "ChangeBitmapRGBLevels"
      
      GFXLIB_CoreCode% += 0
      IF GFXLIB_CoreCode% = 0 THEN ERROR 0, "The GFXLIB core library appears not have been installed and initialised. The core library must be installed and initialised before attempting to install any external GFXLIB modules."
      
      codeSize% = 128
      DIM GFXLIB_ChangeBitmapRGBLevels% codeSize%-1, L% -1
      DIM _{lp%}
      
      IF V% THEN
        PRINT '" Assembling GFXLIB module " + CHR$34 + M$ + CHR$34 + "..."
      ENDIF
      
      FOR I% = 8 TO 10 STEP 2
        
        P% = GFXLIB_ChangeBitmapRGBLevels%
        
        [OPT I%
        
        ;
        ; pSrc, pDst, nPxls, pTbl
        ;
        
        pushad
        
        ; ESP!36 = pSrc
        ; ESP!40 = pDst
        ; ESP!44 = nPxls
        ; ESP!48 = pTbl
        
        mov edi, [esp + 36]            ; EDI = pSrc
        mov esi, [esp + 40]            ; ESI = pDst
        mov edx, [esp + 44]            ; EDX = nPxls
        mov ebp, [esp + 48]            ; EBP = pTbl
        
        xor eax, eax
        xor ebx, ebx
        xor ecx, ecx                   ; ECX = pixel index
        
        ._.lp%
        
        mov al, [edi + 4*ecx + 0]      ; load blue byte from src
        mov bl, [ebp + 4*eax + 0]      ; load corresponding blue value from tbl
        mov [esi + 4*ecx + 0], bl      ; store blue byte in dst
        
        mov al, [edi + 4*ecx + 1]      ; load green byte from src
        mov bl, [ebp + 4*eax + 1]      ; load corresponding green value from tbl
        mov [esi + 4*ecx + 1], bl      ; store green byte in dst
        
        mov al, [edi + 4*ecx + 2]      ; load red byte from src
        mov bl, [ebp + 4*eax + 2]      ; load corresponding red value from tbl
        mov [esi + 4*ecx + 2], bl      ; store red byte in dst
        
        add ecx, 1
        cmp ecx, edx
        jl _.lp%
        
        popad
        ret 20
        
        ]
        
      NEXT I%
      
      IF V% THEN
        PRINT " Assembled code size = "; (P% - GFXLIB_ChangeBitmapRGBLevels%);" bytes"
        WAIT V%
      ENDIF
      
      ENDPROC 




Here's the source program for Example 1:
Code:
      *ESC OFF
      *FLOAT 64
      
      ON ERROR PROCerror( REPORT$, TRUE )
      
      HIMEM = LOMEM + 2*&100000
      
      REM. Prevent the user from resizing the program window
      REM. (although they can still minimise it)
      PROCfixWindowSize
      
      MODE 8
      OFF
      
      INSTALL @lib$+"GFXLIB2" : PROCInitGFXLIB
      INSTALL @lib$+"GFXLIB_modules\ChangeBitmapRGBLevels" : PROCInitModule
      
      bm% = FNLoadImg( @lib$ + "GFXLIB_media\bg1_640x512x8.bmp", 0 )
      
      DIM table{(255) b&, g&, r&, a&}
      
      *REFRESH OFF
      
      REPEAT
        
        T% = TIME
        
        FOR I% = 0 TO 255
          t# = 2*PI * I%/255
          table{(I%)}.r& = 128 + 127*SIN(t# + T%/180)
          table{(I%)}.g& = 128 + 127*COS(t# - T%/170)
          table{(I%)}.b& = 128 + 127*SIN(t# + T%/160)*COS(t# - T%/220)
        NEXT I%
        
        SYS GFXLIB_ChangeBitmapRGBLevels%, bm%, dispVars.bmBuffAddr%, 640*512, ^table{(0)}.b&
        
        PROCdisplay
        
      UNTIL FALSE
      END
      :
      :
      :
      :
      DEF PROCfixWindowSize
      LOCAL GWL_STYLE, WS_THICKFRAME, WS_MAXIMIZEBOX, ws%
      GWL_STYLE = -16
      WS_THICKFRAME = &40000
      WS_MAXIMIZEBOX = &10000
      SYS "GetWindowLong", @hwnd%, GWL_STYLE TO ws%
      SYS "SetWindowLong", @hwnd%, GWL_STYLE, ws% AND NOT (WS_THICKFRAME+WS_MAXIMIZEBOX)
      ENDPROC
      :
      :
      :
      :
      DEF PROCerror( msg$, L% )
      OSCLI "REFRESH ON" : ON
      COLOUR 1, &FF, &FF, &FF
      COLOUR 1
      PRINT TAB(1,1)msg$;
      IF L% THEN
        PRINT " at line "; ERL;
      ENDIF
      VDU 7
      REPEAT UNTIL INKEY(1)=0
      ENDPROC 


Re: GFXLIB2: ChangeBitmapRGBLevels
Post by admin on Oct 14th, 2011, 5:45pm

on Oct 14th, 2011, 04:46am, David Williams wrote:
I bet I end up re-naming this new routine.

I tried writing an MMX version, but it was about three times slower! MMX is simply not suited to table look-up, despite the pextrw and pinsrw instructions which were added at the SSE stage to address that issue to a degree.

Richard.
Re: GFXLIB2: ChangeBitmapRGBLevels
Post by David Williams on Oct 15th, 2011, 12:29pm

on Oct 14th, 2011, 5:45pm, Richard Russell wrote:
I tried writing an MMX version, but it was about three times slower! MMX is simply not suited to table look-up, despite the pextrw and pinsrw instructions which were added at the SSE stage to address that issue to a degree.


Thanks for trying anyway! Your attempt is appreciated.

Perhaps a re-ordering of the instructions in the current non-MMX code; somehow doing all the reads first - source pixel reads, then the table reads, then do all the writes might lead to faster execution. Registers aren't exactly in abundance, so it'll be tricky. I may still give it a crack.


Rgs,
David.