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