Save/Restore the GRAPHICS MODE
Posted: Tue Aug 14, 2018 4:41 pm
Functions provided:
Library File
Test File
Background/Details:
A while ago I requested a new command GET GRAPHICS MODE M$ and the ability to use a string variable when setting the graphics mode (requested here). Since then I've just resigned myself to knowing that I cannot preserve the graphics mode if I have a function that needs to set it to a specific mode.
Then I stumbled on Joel's post where he shared his save_graphic_params library function, with his clever method of saving a portion of the graphics window to an image, drawing to that space, using the GET PIXEL COLOR command to detect what the graphics settings are set to, and then drawing the saved image back onto the screen. I thought this was really cool, but I realized that it assumes that the graphics mode is set to NORMAL and that the portion of the screen being saved and redrawn is fully opaque.
This inspired me to try and write my own library functions for saving/restoring the graphics mode, and the goal was that it would detect the graphics mode without doing anything like setting the FILL COLOR and FILL ALPHA. I wanted this function to be able to be used by Joel's library so it could set graphics mode to NORMAL for drawing, set it to COPY for drawing back the portion of the screen that was saved (preserving transparency), and then return it back to the original mode. I went back a forth a few times between being hopeful and believing it was impossible, but I finally discovered the right combination of smart Basic features that enable the graphics mode to be detected without setting any graphics parameters like FILL COLOR or FILL ALPHA:
- GET_GRAPHICS_MODE$ () detects the current graphics mode and returns it as a string (e.g. "NORMAL", "MULTIPLY", "SCREEN", etc.).
- SET_GRAPHICS_MODE (gm$) sets the graphics mode based on the input string.
- SAVE_GRAPHICS_MODE () calls GET_GRAPHICS_MODE$ and stores the returned mode string so that the graphics mode can be restored to that mode at a later time using RESTORE_GRAPHICS_MODE.
- RESTORE_GRAPHICS_MODE () uses the mode string stored by SAVE_GRAPHICS_MODE and calls SET_GRAPHICS_MODE(gm$).
Library File
Code: Select all
'g'
/*
GET_GRAPHICS_MODE$ ()
SET_GRAPHICS_MODE (gm$)
SAVE_GRAPHICS_MODE ()
RESTORE_GRAPHICS_MODE ()
Functions for detecting, setting, saving, and restoring the graphics mode.
'==============================================================
GET_GRAPHICS_MODE$ detects the current graphics mode and returns it as a string (e.g. "NORMAL", "MULTIPLY", "SCREEN", etc.).
SET_GRAPHICS_MODE sets the graphics mode based on the input string.
Inputs
------
gm$ Graphics mode string (e.g. "MULTIPLY")
'==============================================================
SAVE_GRAPHICS_MODE calls GET_GRAPHICS_MODE$ and stores the returned mode string so that the graphics mode can be restored to that mode at a later time using RESTORE_GRAPHICS_MODE.
RESTORE_GRAPHICS_MODE uses the mode string stored by SAVE_GRAPHICS_MODE and calls SET_GRAPHICS_MODE(gm$).
'==============================================================
*/
''
DEF GET_GRAPHICS_MODE$ ()
r1 = 0.7 ! r2 = 0.1
g1 = 0.0 ! g2 = 0.3
b1 = 1.0 ! b2 = 0.7
a1 = 0.2 ! a2 = 0.9
nScan$ = "get_graphics_mode_scan"
SPRITE nScan$ SCAN 0, 0, 2, 2
DRAW PIXEL 0, 0 COLOR r1, g1, b1, a1
nStamp$ = "get_graphics_mode_stamp"
SPRITE nStamp$ BEGIN 1, 1
GRAPHICS CLEAR r2, g2, b2, a2
SPRITE END
SPRITE nStamp$ STAMP
GET PIXEL 0, 0 COLOR r, g, b, a
r$ = INT(r*255)
g$ = INT(g*255)
b$ = INT(b*255)
a$ = INT(a*255)
c$ = r$ & "-" & g$ & "-" & b$ & "-" & a$
IF c$ = "28-75-180-235" THEN gm$ = "NORMAL"
IF c$ = "26-60-180-235" THEN gm$ = "MULTIPLY"
IF c$ = "59-75-194-235" THEN gm$ = "SCREEN"
IF c$ = "44-60-194-235" THEN gm$ = "OVERLAY"
IF c$ = "28-60-180-235" THEN gm$ = "DARKEN"
IF c$ = "58-75-194-235" THEN gm$ = "LIGHTEN"
IF c$ = "61-60-255-235" THEN gm$ = "COLORDODGE"
IF c$ = "0-0-194-235" THEN gm$ = "COLORBURN"
IF c$ = "49-60-194-235" THEN gm$ = "SOFTLIGHT"
IF c$ = "30-60-194-235" THEN gm$ = "HARDLIGHT"
IF c$ = "52-75-160-235" THEN gm$ = "DIFFERENCE"
IF c$ = "55-75-160-235" THEN gm$ = "EXCLUSION"
IF c$ = "23-76-194-235" THEN gm$ = "HUE"
IF c$ = "50-66-181-235" THEN gm$ = "SATURATION"
IF c$ = "29-76-181-235" THEN gm$ = "COLOR"
IF c$ = "52-60-187-235" THEN gm$ = "LUMINOSITY"
IF c$ = "0-0-0-0" THEN gm$ = "CLEAR"
IF c$ = "26-77-179-230" THEN gm$ = "COPY"
IF c$ = "28-78-183-46" THEN gm$ = "SOURCEIN"
IF c$ = "26-78-179-184" THEN gm$ = "SOURCEOUT"
IF c$ = "40-65-185-51" THEN gm$ = "SOURCEATOP"
IF c$ = "58-60-194-235" THEN gm$ = "DESTOVER"
IF c$ = "177-0-255-46" THEN gm$ = "DESTIN"
IF c$ = "204-0-255-5" THEN gm$ = "DESTOUT"
IF c$ = "54-61-193-230" THEN gm$ = "DESTATOP"
IF c$ = "28-74-179-189" THEN gm$ = "XOR"
IF c$ = "32-43-186-255" THEN gm$ = "PLUSDARKER"
IF c$ = "58-69-212-255" THEN gm$ = "PLUSLIGHTER"
GRAPHICS MODE COPY
SPRITE nScan$ STAMP
SET_GRAPHICS_MODE(gm$)
RETURN gm$
END DEF
'==============================================================
DEF SET_GRAPHICS_MODE (gm$)
gm$ = CAPSTR$(gm$)
IF gm$ = "NORMAL" THEN GRAPHICS MODE NORMAL
IF gm$ = "MULTIPLY" THEN GRAPHICS MODE MULTIPLY
IF gm$ = "SCREEN" THEN GRAPHICS MODE SCREEN
IF gm$ = "OVERLAY" THEN GRAPHICS MODE OVERLAY
IF gm$ = "DARKEN" THEN GRAPHICS MODE DARKEN
IF gm$ = "LIGHTEN" THEN GRAPHICS MODE LIGHTEN
IF gm$ = "COLORDODGE" THEN GRAPHICS MODE COLORDODGE
IF gm$ = "COLORBURN" THEN GRAPHICS MODE COLORBURN
IF gm$ = "SOFTLIGHT" THEN GRAPHICS MODE SOFTLIGHT
IF gm$ = "HARDLIGHT" THEN GRAPHICS MODE HARDLIGHT
IF gm$ = "DIFFERENCE" THEN GRAPHICS MODE DIFFERENCE
IF gm$ = "EXCLUSION" THEN GRAPHICS MODE EXCLUSION
IF gm$ = "HUE" THEN GRAPHICS MODE HUE
IF gm$ = "SATURATION" THEN GRAPHICS MODE SATURATION
IF gm$ = "COLOR" THEN GRAPHICS MODE COLOR
IF gm$ = "LUMINOSITY" THEN GRAPHICS MODE LUMINOSITY
IF gm$ = "CLEAR" THEN GRAPHICS MODE CLEAR
IF gm$ = "COPY" THEN GRAPHICS MODE COPY
IF gm$ = "SOURCEIN" THEN GRAPHICS MODE SOURCEIN
IF gm$ = "SOURCEOUT" THEN GRAPHICS MODE SOURCEOUT
IF gm$ = "SOURCEATOP" THEN GRAPHICS MODE SOURCEATOP
IF gm$ = "DESTOVER" THEN GRAPHICS MODE DESTOVER
IF gm$ = "DESTIN" THEN GRAPHICS MODE DESTIN
IF gm$ = "DESTOUT" THEN GRAPHICS MODE DESTOUT
IF gm$ = "DESTATOP" THEN GRAPHICS MODE DESTATOP
IF gm$ = "XOR" THEN GRAPHICS MODE XOR
IF gm$ = "PLUSDARKER" THEN GRAPHICS MODE PLUSDARKER
IF gm$ = "PLUSLIGHTER" THEN GRAPHICS MODE PLUSLIGHTER
END DEF
'==============================================================
DEF SAVE_GRAPHICS_MODE ()
gm$ = GET_GRAPHICS_MODE$()
END DEF
'==============================================================
DEF RESTORE_GRAPHICS_MODE ()
SET_GRAPHICS_MODE(SAVE_GRAPHICS_MODE.gm$)
END DEF
'==============================================================
Code: Select all
{graphics_modes}
GRAPHICS CLEAR
GRAPHICS
DRAW ALPHA 0
FILL ALPHA 0
DIM gm$(28)
gm$(0) = "NORMAL"
gm$(1) = "MULTIPLY"
gm$(2) = "SCREEN"
gm$(3) = "OVERLAY"
gm$(4) = "DARKEN"
gm$(5) = "LIGHTEN"
gm$(6) = "COLORDODGE"
gm$(7) = "COLORBURN"
gm$(8) = "SOFTLIGHT"
gm$(9) = "HARDLIGHT"
gm$(10) = "DIFFERENCE"
gm$(11) = "EXCLUSION"
gm$(12) = "HUE"
gm$(13) = "SATURATION"
gm$(14) = "COLOR"
gm$(15) = "LUMINOSITY"
gm$(16) = "CLEAR"
gm$(17) = "COPY"
gm$(18) = "SOURCEIN"
gm$(19) = "SOURCEOUT"
gm$(20) = "SOURCEATOP"
gm$(21) = "DESTOVER"
gm$(22) = "DESTIN"
gm$(23) = "DESTOUT"
gm$(24) = "DESTATOP"
gm$(25) = "XOR"
gm$(26) = "PLUSDARKER"
gm$(27) = "PLUSLIGHTER"
FOR i = 0 TO 27
SET_GRAPHICS_MODE(gm$(i))
gm_detected$ = GET_GRAPHICS_MODE$()
IF gm$(i) = gm_detected$ THEN
' Test passed
t$ &= "."
ELSE
' Test failed
t$ &= "F" & CHR$(13)
t$ &= gm$(i) & " -> " & gm_detected$ & CHR$(13)
END IF
NEXT i
PAUSE 1
TEXT
PRINT t$
A while ago I requested a new command GET GRAPHICS MODE M$ and the ability to use a string variable when setting the graphics mode (requested here). Since then I've just resigned myself to knowing that I cannot preserve the graphics mode if I have a function that needs to set it to a specific mode.
Then I stumbled on Joel's post where he shared his save_graphic_params library function, with his clever method of saving a portion of the graphics window to an image, drawing to that space, using the GET PIXEL COLOR command to detect what the graphics settings are set to, and then drawing the saved image back onto the screen. I thought this was really cool, but I realized that it assumes that the graphics mode is set to NORMAL and that the portion of the screen being saved and redrawn is fully opaque.
This inspired me to try and write my own library functions for saving/restoring the graphics mode, and the goal was that it would detect the graphics mode without doing anything like setting the FILL COLOR and FILL ALPHA. I wanted this function to be able to be used by Joel's library so it could set graphics mode to NORMAL for drawing, set it to COPY for drawing back the portion of the screen that was saved (preserving transparency), and then return it back to the original mode. I went back a forth a few times between being hopeful and believing it was impossible, but I finally discovered the right combination of smart Basic features that enable the graphics mode to be detected without setting any graphics parameters like FILL COLOR or FILL ALPHA:
- The arguments for the DRAW PIXEL COLOR command are absolute (r, g, b, and a are not affected by the graphics mode or draw/fill settings). Therefore, this command can be used to draw a specific and known base color to the graphics window without using FILL COLOR or FILL ALPHA.
- Because sprites are "separate graphics layers," they have their own graphics mode independent of the main graphics window, so when drawing to a sprite the graphics mode defaults to NORMAL (and when calling SPRITE END and returning to the main graphics window, the main graphics mode is preserved). This fact can be used to create a sprite that is filled with a second color by using GRAPHICS CLEAR R, G, B, A, which doesn't require the use of FILL COLOR and FILL ALPHA.
- Stamping a sprite is dependent on the graphics mode, so we can stamp the sprite from #2 over the pixels drawn in #1, read the resulting R, G, B, and alpha values, and then determine the graphics mode.