Area: Quik_Bas Msg: #701 Date: 06-18-92 06:56 (Public) From: Steve Gartrell To: All Subject: Screen Compressor
'Sometimes I'm sort of dense, especially when the subject
'is fairly technical, and I don't have the time to focus
'on it. Such was my experience with Rich Geldreich's
'excellent example of Huffman compression used in saving
'screen 13 graphics. I got frustrated, and wrote my own
'compression program instead. Amusingly, it runs significantly
'faster than the Huffman routine, while paying around a
'10% penalty in compressed size in screen 13. Both a screen
'13 version and a screen 12 version are included. I have
'seen the 307,000 pixels involved in screen 12 compressed to
'roughly 31,000 bytes; an equivalent GET/BSAVE of all four
'bitplanes would yield over 1.2 MBytes of files. This is
'all native QB source code => it could be made faster yet.
'How does it work? The trick is the likelihood that at
'least some pixels adjacent to each other on the same
'row or column, dependent upon screen mode, will be the
'same color. In 16 color modes, you need 4 bits to store
'any pixel's color. QB/PDS happen to have 16 bits available
'in their smallest numeric data type. In 16 color modes,
'that means that by left-shifting the color bits, you can
'use the lower bits to count the number of adjacent pixels
'of the same color. Since 640 pixels use only through the
'10th least significant bit, you can describe all of the
'colors of an entire row, assuming they are the _same_ color,
'in one integer. Thus, you can conceivably describe a mode
'12 screen that was blank using just 480 integers, or 960
'bytes. In screen 13, it takes 8 bits to describe a color.
'This left me with just eight bits for pixel counting; thus
'the vertical (by column) count as 200 uses through the 8th
'least significant bit. Of course, I had to figure out some
'contortions to use the 16th bit, since QB/PDS insists on
'signed integers. A caveat; in 16 bit modes, you normally
'could pack a 16-bit integer with 4 pixel colors, thus any
'screen that rarely sees 4 same color pixels adjacent could
'conceivably be stored inefficiently. Likewise, two pixels
'could be stored in an integer in mode 12, requiring the
'appearance of two sequential same color bits to maintain
'storage parity.
'
'Do use the PDS/QB /ah switch before loading....And do
'leave my name in the source, and credit me if you are
'going to make money from it!!!...<g>....|-}
DEFINT A-Z
DECLARE SUB FourBits ()
CONST BufSize% = 32766
CONST MaxedOut% = 32767
CONST C$ = "Created 06/17/92 by Steve Gartrell. No rights reserved."
SCREEN 13, , 0, 0
REDIM SHARED FileBuffer%(1 TO 32000)
FourBits
SCREEN 13
'make some graphics-borrowed from Rich Geldreich!!!
FOR A = 1 TO 400
RANDOMIZE TIMER
IF RND > .05 THEN
LINE -(RND * 320, RND * 200), RND * 255
ELSE
LINE -(RND * 320, RND * 200), RND * 255, BF
END IF
NEXT
COLOR 15
LOCATE 25, 1: PRINT "320 x 200";
filenum% = FREEFILE
OPEN "256PRESS.GRF" FOR BINARY AS filenum%
IF LOF(filenum%) <> 0 THEN
CLOSE filenum%
KILL "256PRESS.GRF"
ELSE
CLOSE filenum%
END IF
cell% = 1
ByteCnt& = 1
FOR x% = 0 TO 319
CurColorPix% = POINT(x%, 0)
ColorWord& = CurColorPix% * &H100&
FOR y% = 0 TO 199
ThisPixColor% = POINT(x%, y%)
PRESET (x%, y%), 0
IF ThisPixColor% = CurColorPix% THEN
ColorWord& = ColorWord& + 1
ELSE
IF ColorWord& > 32767 THEN
ColorWord& = ((-ColorWord& - 1) XOR &HFFFFFFFF) - 65536
END IF
FileBuffer%(cell%) = CINT(ColorWord&)
cell% = cell% + 1
CurColorPix% = ThisPixColor%
ColorWord& = CurColorPix% * &H100& + 1&
END IF
NEXT
IF ColorWord& > 32767 THEN
ColorWord& = ((-ColorWord& - 1) XOR &HFFFFFFFF) - 65536
END IF
FileBuffer%(cell%) = CINT(ColorWord&)
cell% = cell% + 1
NEXT
cell& = cell% * 2&
DEF SEG = VARSEG(FileBuffer%(1))
BSAVE "256PRESS.GRF", VARPTR(FileBuffer%(1)), cell&
DEF SEG
CLOSE #filenum%
BEEP: BEEP: BEEP
LOCATE 9, 1
PRINT "Screen reduced to "; LTRIM$(STR$(cell&)); " bytes.";
LOCATE 10, 1: PRINT "Press any key to decompress.";
DO: LOOP UNTIL INKEY$ <> ""
filenum% = FREEFILE
OPEN "256PRESS.GRF" FOR BINARY AS filenum%
cell% = LOF(filenum%) \ 2
CLOSE filenum%
REDIM FileBuffer%(1 TO cell%)
DEF SEG = VARSEG(FileBuffer%(1))
BLOAD "256PRESS.GRF", VARPTR(FileBuffer%(1))
DEF SEG
CLS
ByteCnt& = 1
BitCnt% = 0
x% = 0
FOR cnt% = 1 TO cell%
ColorWord% = FileBuffer%(cnt%)
IF ColorWord% < 0 THEN
ColorWord& = ABS(((CLNG(ColorWord%) + 65536) XOR &HFFFF) + 1)
ELSE
ColorWord& = CLNG(ColorWord%)
END IF
ByteCnt& = ByteCnt& + 2
PixCnt% = ColorWord& MOD &H100
PixColor% = ColorWord& \ &H100
COLOR PixColor%
FOR ThisPix% = BitCnt% TO (BitCnt% + PixCnt%) - 1
PSET (x%, ThisPix%)
NEXT
BitCnt% = BitCnt% + PixCnt%
IF ThisPix% = 200 THEN
BitCnt% = 0
x% = x% + 1
IF x% = 320 THEN
EXIT FOR
END IF
END IF
NEXT
BEEP: BEEP: BEEP
DO: LOOP UNTIL INKEY$ <> ""
SCREEN 0
WIDTH 80
COLOR 7, 0
END
SUB FourBits
REDIM FileBuffer%(1 TO BufSize%)
SCREEN 12
'make some graphics-borrowed from Rich Geldreich!
FOR A = 1 TO 400
RANDOMIZE TIMER
IF RND > .05 THEN
LINE -(RND * 640, RND * 480), RND * 255 MOD 16
ELSE
LINE -(RND * 640, RND * 480), RND * 255 MOD 16, BF
END IF
NEXT
COLOR 15
LOCATE 30, 1: PRINT "640 x 480";
filenum% = FREEFILE
OPEN "16PRESS.GRF" FOR BINARY AS filenum%
IF LOF(filenum%) <> 0 THEN
CLOSE filenum%
KILL "16PRESS.GRF"
filenum% = FREEFILE
OPEN "16PRESS.GRF" FOR BINARY AS filenum%
END IF
MaxedFlag% = 0
ByteCnt& = 1
cell% = 1
FOR y% = 0 TO 479
CurColorPix% = POINT(0, y%)
-end-

Books at Amazon:
Back to BASIC: The History, Corruption, and Future of the Language
Hackers: Heroes of the Computer Revolution (including Tiny BASIC)
Go to: The Story of the Math Majors, Bridge Players, Engineers, Chess Wizards, Scientists and Iconoclasts who were the Hero Programmers of the Software Revolution
The Advent of the Algorithm: The Idea that Rules the World
Moths in the Machine: The Power and Perils of Programming
Mastering Visual Basic .NET