pcx viewer help
Posted: Sat Feb 08, 2003 8:42 am
I've got a subprogram that shows pcx files, and what I want to do is send it, the pcx, to a buffer and get it from there somehow. Here's the sub program:
SUB showpcx (file$)
SCREEN 13
DIM pcxpal AS STRING * 768, pcxversion AS STRING * 1
pcxnum = FREEFILE
OPEN file$ FOR BINARY AS #pcxnum
'*** Get the PCX version from the header.
GET #pcxnum, 2, pcxversion
'*** If we're using version 5, then load the palette.
IF ASC(pcxversion) = 5 THEN
'*** Grab the palette out of the file.
GET #1, LOF(pcxnum) - 767, pcxpal
'*** Start with color 0.
pal = 0
'*** Grab the red/green/blue value from our palette (PCXPAL) and
'*** send them to the monitor using OUT.
FOR p = 1 TO 768 STEP 3
OUT &H3C8, pal
red% = INT(ASC(MID$(pcxpal, p, 1)) / 4)
OUT &H3C9, red%
green% = INT(ASC(MID$(pcxpal, p + 1, 1)) / 4)
OUT &H3C9, green%
blue% = INT(ASC(MID$(pcxpal, p + 2, 1)) / 4)
OUT &H3C9, blue%
pal = pal + 1
NEXT p
END IF
'*** Jump past the file header.
SEEK #pcxnum, 129
'*** We'll be sending the output the the screen, so our segment
'*** is &HA000 (VGA screen memory) and our offset is 0. You can
'*** change these values to, say, decompress the image into an
'*** array or something.
fxoffset = 0: fxsegment = &HA000
'*** We'll be reading chunks of 2,000 bytes. You can increase or
'*** decrease this depending on your needs. I noticed little or
'*** no difference when the chunk size went past 2,000, so I left
'*** it at 2,000 to add as little over-head as possible with maximum
'*** speed.
datasize = 2000
'*** Load our first chunk of data and point to the beginning of that
'*** data.
pcxdata$ = INPUT$(datasize, pcxnum)
datacount = 1
'*** To increase speed, we'll be drawing the screen in two loops,
'*** that way we can use integers to point to the next pixel instead
'*** of long integers. Doing this gains tremendous speed.
FOR half = 1 TO 2
'*** On the second loop, this will add &H7D0 (32000) to our
'*** segment so we'll be writing to the second half of the screen.
'*** On the first loop, this will simply set our segment to &HA000.
fxtotal = fxsegment + fxoffset
DEF SEG = fxtotal
FOR c = 0 TO 31999
'*** If we're out of data, then we need to load the next chunk.
IF datacount > datasize THEN
pcxdata$ = INPUT$(datasize, pcxnum)
datacount = 1
END IF
'*** Get the next byte from our data chunk.
clr = ASC(MID$(pcxdata$, datacount, 1))
datacount = datacount + 1
'*** If we're out of data, then we load the next chunk.
IF datacount > datasize THEN
pcxdata$ = INPUT$(datasize, pcxnum)
datacount = 1
END IF
'*** If the byte we pulled from the data has bit 6 and 7 set,
'*** (which would make the value greater than 192), then that
'*** means we'll be repeating a color. So we pull the next
'*** byte from our data chunk (which is the color), and put
'*** it on the screen CLR - 192 times (in other words, we
'*** take the value of the first 5 bits in the byte and put
'*** the pixel to the screen that many times.)
IF clr > 192 THEN
LPS = clr - 192
clr = ASC(MID$(pcxdata$, datacount, 1))
datacount = datacount + 1
FOR L = LPS TO 1 STEP -1
POKE c, clr
c = c + 1
NEXT L
c = c - 1
ELSE
'*** Since the byte was less than 192, then we just poke the
'*** pixel to the screen.
POKE c, clr
END IF
NEXT c
'*** We'll move to the second half of the screen by adding 32,000
'*** (HEX = 7D0) bytes to our segment value.
fxoffset = fxoffset + &H7D0
NEXT half
'*** All done! Close the file.
CLOSE pcxnum
'*** Return to BASIC's default segment. Very important!
DEF SEG
END SUB
SUB showpcx (file$)
SCREEN 13
DIM pcxpal AS STRING * 768, pcxversion AS STRING * 1
pcxnum = FREEFILE
OPEN file$ FOR BINARY AS #pcxnum
'*** Get the PCX version from the header.
GET #pcxnum, 2, pcxversion
'*** If we're using version 5, then load the palette.
IF ASC(pcxversion) = 5 THEN
'*** Grab the palette out of the file.
GET #1, LOF(pcxnum) - 767, pcxpal
'*** Start with color 0.
pal = 0
'*** Grab the red/green/blue value from our palette (PCXPAL) and
'*** send them to the monitor using OUT.
FOR p = 1 TO 768 STEP 3
OUT &H3C8, pal
red% = INT(ASC(MID$(pcxpal, p, 1)) / 4)
OUT &H3C9, red%
green% = INT(ASC(MID$(pcxpal, p + 1, 1)) / 4)
OUT &H3C9, green%
blue% = INT(ASC(MID$(pcxpal, p + 2, 1)) / 4)
OUT &H3C9, blue%
pal = pal + 1
NEXT p
END IF
'*** Jump past the file header.
SEEK #pcxnum, 129
'*** We'll be sending the output the the screen, so our segment
'*** is &HA000 (VGA screen memory) and our offset is 0. You can
'*** change these values to, say, decompress the image into an
'*** array or something.
fxoffset = 0: fxsegment = &HA000
'*** We'll be reading chunks of 2,000 bytes. You can increase or
'*** decrease this depending on your needs. I noticed little or
'*** no difference when the chunk size went past 2,000, so I left
'*** it at 2,000 to add as little over-head as possible with maximum
'*** speed.
datasize = 2000
'*** Load our first chunk of data and point to the beginning of that
'*** data.
pcxdata$ = INPUT$(datasize, pcxnum)
datacount = 1
'*** To increase speed, we'll be drawing the screen in two loops,
'*** that way we can use integers to point to the next pixel instead
'*** of long integers. Doing this gains tremendous speed.
FOR half = 1 TO 2
'*** On the second loop, this will add &H7D0 (32000) to our
'*** segment so we'll be writing to the second half of the screen.
'*** On the first loop, this will simply set our segment to &HA000.
fxtotal = fxsegment + fxoffset
DEF SEG = fxtotal
FOR c = 0 TO 31999
'*** If we're out of data, then we need to load the next chunk.
IF datacount > datasize THEN
pcxdata$ = INPUT$(datasize, pcxnum)
datacount = 1
END IF
'*** Get the next byte from our data chunk.
clr = ASC(MID$(pcxdata$, datacount, 1))
datacount = datacount + 1
'*** If we're out of data, then we load the next chunk.
IF datacount > datasize THEN
pcxdata$ = INPUT$(datasize, pcxnum)
datacount = 1
END IF
'*** If the byte we pulled from the data has bit 6 and 7 set,
'*** (which would make the value greater than 192), then that
'*** means we'll be repeating a color. So we pull the next
'*** byte from our data chunk (which is the color), and put
'*** it on the screen CLR - 192 times (in other words, we
'*** take the value of the first 5 bits in the byte and put
'*** the pixel to the screen that many times.)
IF clr > 192 THEN
LPS = clr - 192
clr = ASC(MID$(pcxdata$, datacount, 1))
datacount = datacount + 1
FOR L = LPS TO 1 STEP -1
POKE c, clr
c = c + 1
NEXT L
c = c - 1
ELSE
'*** Since the byte was less than 192, then we just poke the
'*** pixel to the screen.
POKE c, clr
END IF
NEXT c
'*** We'll move to the second half of the screen by adding 32,000
'*** (HEX = 7D0) bytes to our segment value.
fxoffset = fxoffset + &H7D0
NEXT half
'*** All done! Close the file.
CLOSE pcxnum
'*** Return to BASIC's default segment. Very important!
DEF SEG
END SUB