Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Masking an image. 2

Status
Not open for further replies.

quebasic2

Programmer
Dec 17, 2002
174
IN
In my program, I load my graphics from a gif file. But, on my character graphic, I need a mask for when I am moveing it around. How can I do that since it is a .gif file.
 
Well you should be a little more specific. Are u using some library? If not and u are using only qb routines then u might want to first 'GET'(see GET and PUT graphics commands) the image and then experiment with the AND, OR, XOR commands.

Alternatively u could write your own put routine i.e. if u are using a custom routine to load your gifs. For example you have a gif file which has a picture of a ball. The ball is circular but when the picture is actually drawn the corners are visible. What u could do is u can decide an invisible color that will denote only transparent region of the picture and when u are drawing the picture pixel by pixel u just check whether the color of the pixel is the transparent color if so then u don't draw anything over there and just move on to the next pixel.
In the ball example u could color the corners with the transparent color and thus avoid displaying those corners.
 
I know how to use GET, PUT, AND, OR. I know how to mask an image using color 255 ie:
DIM GRAPHIC(19), GRAPHICM(19)
SCREEN 13
CLS
CIRCLE (5, 5), 5, 1
GET (0, 0)-(10, 10), GRAPHIC
CLS
LINE (0, 0)-(10, 10), 255, BF
CIRCLE (5, 5), 5, 1
GET (0, 0)-(10, 10), GRAPHICM
CLS
PUT (0, 0), GRAPHICM, AND
PUT (0, 0), GRAPHIC, OR

However, since I am not drwing my graphics in the program, but I am extracting them from a gif file, I don't know how to make the mask (the image with the 255 color for the background).
 
What format are you reading the gif into? PUT format, or a multidimensional array? You should just write your own drawing routine.

(Are you using SCREEN 13? I know most about that)

-----------------------
Soon to come - a QBasic contest forum!
-----------------------
 
Just draw that gif image on the screen. Then using GET, get it into an array and then just use the masking routine using color 255 in screen 13 that u mentioned earlier
 
But how do I get the image with 255 color? The program draws the graphic to the screen, I GET it. Then I need to make another image like that, but with a background of 255.
 
>>The program draws the graphic to the screen, I GET it.

do you have the source for the program...

If you do, post it (the gif loading part) here and one of us can help you change it so that it will write to memory instead of the screen...

Have Fun, Be Young... Code BASIC
-Josh Stribling
cubee101.gif

 
Here is the code. It is a free gif loader that I just downloaded of a website. My program runs in screen 13.

SUB GifLoad (a$)

'Loads a .gif picture. I'm not good enough at programming to do this myself,
'so I just downloaded it from qbasic.com :)

DEFINT A-Z
DIM Prefix(4095), Suffix(4095), OutStack(4095), shiftout%(8)
DIM Ybase AS LONG, powersof2(11) AS LONG, WorkCode AS LONG

FOR a% = 0 TO 7: shiftout%(8 - a%) = 2 ^ a%: NEXT a%
FOR a% = 0 TO 11: powersof2(a%) = 2 ^ a%: NEXT a%
IF a$ = "" THEN INPUT "GIF file"; a$: IF a$ = "" THEN END
IF INSTR(a$, ".") = 0 THEN a$ = a$ + ".gif"
OPEN a$ FOR BINARY AS #1
a$ = " ": GET #1, , a$
IF a$ <> &quot;GIF87a&quot; THEN PRINT &quot;Not a GIF87a file.&quot;: END
GET #1, , TotalX: GET #1, , TotalY: GOSUB GetByte
NumColors = 2 ^ ((a% AND 7) + 1): NoPalette = (a% AND 128) = 0
GOSUB GetByte: Background = a%
GOSUB GetByte: IF a% <> 0 THEN PRINT &quot;Bad screen descriptor.&quot;: END
IF NoPalette = 0 THEN P$ = SPACE$(NumColors * 3): GET #1, , P$
DO
GOSUB GetByte
IF a% = 44 THEN
EXIT DO
ELSEIF a% <> 33 THEN
PRINT &quot;Unknown extension type.&quot;: END
END IF
GOSUB GetByte
DO: GOSUB GetByte: a$ = SPACE$(a%): GET #1, , a$: LOOP UNTIL a% = 0
LOOP
GET #1, , XStart: GET #1, , YStart: GET #1, , XLength: GET #1, , YLength
XEnd = XStart + XLength: YEnd = YStart + YLength: GOSUB GetByte
IF a% AND 128 THEN PRINT &quot;Can't handle local colormaps.&quot;: END
Interlaced = a% AND 64: PassNumber = 0: PassStep = 8
GOSUB GetByte
ClearCode = 2 ^ a%
EOSCode = ClearCode + 1
FirstCode = ClearCode + 2: NextCode = FirstCode
StartCodeSize = a% + 1: CodeSize = StartCodeSize
StartMaxCode = 2 ^ (a% + 1) - 1: MaxCode = StartMaxCode

BitsIn = 0: BlockSize = 0: BlockPointer = 1
X% = XStart: Y% = YStart: Ybase = Y% * 320&

SCREEN 13: DEF SEG = &HA000
IF NoPalette = 0 THEN
OUT &H3C7, 0: OUT &H3C8, 0
FOR a% = 1 TO NumColors * 3: OUT &H3C9, ASC(MID$(P$, a%, 1)) \ 4: NEXT a%
END IF
LINE (0, 0)-(319, 199), Background, BF

DO
GOSUB GetCode
IF Code <> EOSCode THEN
IF Code = ClearCode THEN
NextCode = FirstCode
CodeSize = StartCodeSize
MaxCode = StartMaxCode
GOSUB GetCode
CurCode = Code: LastCode = Code: LastPixel = Code
IF X% < 320 THEN POKE X% + Ybase, LastPixel
X% = X% + 1: IF X% = XEnd THEN GOSUB NextScanLine
ELSE
CurCode = Code: StackPointer = 0
IF Code > NextCode THEN EXIT DO
IF Code = NextCode THEN
CurCode = LastCode
OutStack(StackPointer) = LastPixel
StackPointer = StackPointer + 1
END IF

DO WHILE CurCode >= FirstCode
OutStack(StackPointer) = Suffix(CurCode)
StackPointer = StackPointer + 1
CurCode = Prefix(CurCode)
LOOP

LastPixel = CurCode
IF X% < 320 THEN POKE X% + Ybase, LastPixel
X% = X% + 1: IF X% = XEnd THEN GOSUB NextScanLine

FOR a% = StackPointer - 1 TO 0 STEP -1
IF X% < 320 THEN POKE X% + Ybase, OutStack(a%)
X% = X% + 1: IF X% = XEnd THEN GOSUB NextScanLine
NEXT a%

IF NextCode < 4096 THEN
Prefix(NextCode) = LastCode
Suffix(NextCode) = LastPixel
NextCode = NextCode + 1
IF NextCode > MaxCode AND CodeSize < 12 THEN
CodeSize = CodeSize + 1
MaxCode = MaxCode * 2 + 1
END IF
END IF
LastCode = Code
END IF
END IF
LOOP UNTIL DoneFlag OR Code = EOSCode
'BEEP
'A$ = INPUT$(1)
CLOSE #1

EXIT SUB
 
to :quebasic2
> I need a mask
The easiest thing seems to be create a separate black-and white mask image - in your favourite image editing program.

Another thing I can suggest is to scan all screen (after showing image) with POINT(X,Y) and change color_to_be_transparent to 255.
May be brain-dead approach, but it should work - and you'll understand how.
Kind of
for x...
for y...
if POINT(X,Y)=color_to_be_transparent THEN
Pset(X,Y),255
end if
next
next

BTW to get value of color_to_be_transparent you'll use POINT(X,Y), again.

Hope this (can) help
(probably it would be slow - but you need it to do only once)
 
OK...

this is the code that writes to the screen...

...
SCREEN 13: DEF SEG = &HA000
IF NoPalette = 0 THEN
OUT &H3C7, 0: OUT &H3C8, 0
FOR a% = 1 TO NumColors * 3
OUT &H3C9, ASC(MID$(P$, a%, 1)) \ 4
NEXT a%
END IF
LINE (0, 0)-(319, 199), Background, BF
...
LastPixel = CurCode
IF X% < 320 THEN POKE X% + Ybase, LastPixel
X% = X% + 1: IF X% = XEnd THEN GOSUB NextScanLine

FOR a% = StackPointer - 1 TO 0 STEP -1
IF X% < 320 THEN POKE X% + Ybase, OutStack(a%)
X% = X% + 1: IF X% = XEnd THEN GOSUB NextScanLine
NEXT a%
...

To load this into memory... you only need to change a few things...

' xx& = TotalX * TotalY + 2&
DIM PicBUF(xx&) AS INTEGER 'DECLARE THE BUFFER
...
GET (0,0)-(TotalX,TotalY), PicBUF 'INITIALIZE THE BUFFER
......
SCREEN 13: DEF SEG = &HA000
IF NoPalette = 0 THEN
OUT &H3C7, 0: OUT &H3C8, 0
FOR a% = 1 TO NumColors * 3
OUT &H3C9, ASC(MID$(P$, a%, 1)) \ 4
NEXT a%
END IF
DEF SEG = VARSEG(PicBUF(0))
BufOff& = VARPTR(PicBUF(2)) + CP&

...
LastPixel = CurCode
IF X% < 320 THEN POKE X% + Ybase + BuffOff&, LastPixel
X% = X% + 1: IF X% = XEnd THEN GOSUB NextScanLine

FOR a% = StackPointer - 1 TO 0 STEP -1
IF X% < 320 THEN POKE X% + Ybase + BufOff&, OutStack(a%)
X% = X% + 1: IF X% = XEnd THEN GOSUB NextScanLine
NEXT a%
...



DIM SCRNBUF(32002) AS INTEGER 'DECLARE THE BUFFER
...
GET (0,0)-(319,199), SCRNBUF 'INITIALIZE THE BUFFER
...
DEF SEG = VARSEG(SCRNBUF(0)) 'SETUP THE DATA SEGMENT TO THE BUFFER
BUFOFF& = VARPTR(SCRNBUF(2)) + CP& '... AND THE OFFSET

Here is an example of how to use this method to blend 2 buffers (with a gradient palette) into 1 buffer to create a ghost effect...

Code:
DIM SCRNBUF(32002) AS INTEGER
DIM SCRNBUF2(32002) AS INTEGER
...
SCREEN 13
GET (0, 0)-(319, 199), SCRNBUF
GET (0, 0)-(319, 199), SCRNBUF2
...
SUB BLENDBUFS
  FOR CP& = 0 TO 64000
    DEF SEG = VARSEG(SCRNBUF(0))
      CPXL1& = VARPTR(SCRNBUF(2)) + CP&
      C1% = PEEK(CPXL1&)
    DEF SEG
    DEF SEG = VARSEG(SCRNBUF2(0))
      CPXL2& = VARPTR(SCRNBUF2(2)) + CP&
      POKE (CPXL2&), Div2Map(PEEK(CPXL2&) + C1%)
    DEF SEG
  NEXT
  PUT (0, 0), SCRNBUF2, PSET
END SUB

You can also use something similar to this to mask an image...

BTW... its about 3 am and I'm kinda tired... this should get you started... if you can't figure anything out from here, or find errors, just post them back here and I'll help ya out...

Good Luck,
Josh

Have Fun, Be Young... Code BASIC
-Josh Stribling
cubee101.gif

 
How would I chage the color while the file was in memory.
 
write directly to the buffer...

there are several ways to do this...

you can create a screen buffer and an image buffer...

*Also I messed up above, the formula for the array size is:
((X * Y) + 2) / 2

Code:
DIM SHARED SCRBUF(32001) AS INTEGER
DIM SPRITE(201) AS INTEGER
GET(0,0)-(319,199), SCRBUF
GET(0,0)-(19,19), SPRITE

One of the colors in your gif should be transparent

copy the image to the screen buffer, excuding the transparent color, something similar to this...

Code:
DEFINT A-Z
Sub Mask(X, Y,SPRITE(), Trans)
  MaxX = (SPRITE(0) \ 8) - 1
  MaxY = SPRITE(1) - 1
  Off& = VARPTR(SPRITE(2))
  YOff& = Y * 320&
  FOR B = 0 TO MaxY
    FOR A = 0 TO MaxX
      DEF SEG = VARSEG(SPRITE(0))
        C = PEEK(Off&)
        Off& = Off& + 1
      IF C <> Trans THEN
        DEF SEG = VARSEG(SCRBUF(0))
          CPXL2& = VARPTR(SCRBUF(2)) + CP&
          POKE (X + A + YOff&), C 
      END IF
    NEXT
    YOff& = YOff& + 320
  NEXT
  DEF SEG
  PUT (0, 0), SCRBUF, PSET
END SUB

I coded the above from memory...
If you get any errors post them back here and I'll help you with them...

You might want to add some clipping features...

And Avoid using * and / or \ in loops to increase speed while dealing with graphics, + and - are fine...

if you MUST divide or multiply setup a precalculated table in an array to pull from to avoid real time math...

Let me know if you have any questions about the above code.

you might also want to remove...
PUT (0, 0), SCRBUF, PSET
from the sub and put it in the main loop so that it will not redraw after every sprite is placed, this will cut back on flicker...

Another option is to use 3 sprites per sprite...
1) original
2) back buffer
3) masked original on back buffer

Load the sprite into the 1st
using GET grab the same image (same size as sprite) from the background into 2nd & 3rd...

modify the mask sub to write to the 3rd sprite buffer

use PUT to display the 3rd...
use PUT to erase with the 2nd...

Have Fun, Be Young... Code BASIC
-Josh Stribling
cubee101.gif

 
Thanks, I'll try that as soon as possible. My system crashed, so I cannot work on it until I get my computer running again.
 
i made a sub that does it for you, it requires that you have an array called maskcol% with all of the colors you want to be color 255 when make the mask. say you wanted colors 15,17,25,36, and 201 to be masked as color 255 then you would do this

dim shared maskcol%(4)
maskcol%(0)=15
maskcol%(1)=17
maskcol%(2)=25
maskcol%(3)=36
maskcol%(4)=201

after you have that you need the sprite array you have put the gif picture in using GET and you need a seperate picture array to put the mask in...like this

'make mask array
dim mask%(50)
get (0,0)-(10,10),mask%(0)

'load gif routine starts here
...
...
'end of gif loading routine

'load pic in array
Dim gifpic%(50)
get (0,0)-(10,10),gifpic%(0)

after that you just run this function

sub makemask(gifspritesegement%,gifspriteoffset%,maskspritesegment%,maskspriteoffset%,spritewidth,spritehieght)
for x=0 to spritewidth
for y=0 to spritehieght
for m=lbound(maskcol%(0)) to ubound(maskcol%(0))
def seg=gifspritesegment%
col=peek (gifspriteoffset%+x+(y*320))
def seg=maskspritesegment%
poke maskspriteoffset%+x+(y*320),col
if col=m then poke maskspriteoffset%+x+(y*320),255
next m
next y
next x
end sub
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top