'=========================================================================== ' Subject: TGA VIEWER Date: 08-29-96 (18:39) ' Author: Erika Schulze Code: QB, QBasic, PDS ' Origin: 100775.2275@CompuServe.com Packet: GRAPHICS.ABC '=========================================================================== '*************************************************************************** 'Program: TGA.BAS * 'Task: TGA viewer for SCREEN 13 - uncompressed TGA files. * ' Version 1.0 * 'Language: QBASIC mixed with machine code. * 'Author: Erika Schulze * ' CIS: 100775,2275 * ' Internet: 100775.2275@compuserve.com * ' Free for use. * ' Use it, abuse it, but don't blame me! * 'Note: It seems to me that the main problem is reading the data * ' from the disk; that's to slow. If somebody has a better * ' solution for this - your assistance is welcome. Please * ' send me a message with your suggestions for improvements. * '*************************************************************************** 'The TGA (True Version Targa) isn't complicated. There is only a 'TGA header of 18 bytes with all informations about the image. 'Structure of the TGA header: 'Offset Length Description '====== ====== =========== '00H BYTE info: ' It's possible, that after the 18 bytes of the ' header, the file contains an information block. ' This block, for example, holds the copyright ' information. The byte info stands for the ' length of the information block. '01H BYTE colortyp: ' 0 ===> RGB image ' 1 ===> image has a DAC table '02H BYTE imagetyp: ' This byte contains information about the image ' typ: ' 1 ===> uncompressed image datas with a DAC ' table ' 2 ===> uncompressed RGB file ' 9 ===> runlength encoded datas with a DAC table ' 10 ===> runlength encoded RGB file '03H WORD origin: ' This word contains the index of the first entry ' in the DAC table (mostly 0). '05H WORD colnumber: ' This word contains the number of colors in the ' DAC table. That's not the length of the DAC ' table in byte! '07H BYTE entrybits: ' Size of on entry in the DAC table. An entry has ' 16, 24 or 32 bits. '08H WORD xvalue: ' The x-value of the lower left corner of the ' TGA image (mostly 0). '0AH WORD yvalue: ' The y-value of the lower left corner of the ' TGA image (mostly 0). '0CH WORD widt: ' The image width in pixels. '0EH WORD height: ' The image height in pixels. '10H BYTE pixelsize: ' Number of bits per pixel. ' DAC images ===> valid values are 8 and 16 ' RGB images ===> valid values are 16, 24 and 32 '11H BYTE descriptor: ' The image descriptor contains additional ' informations. 'The structure of the image descriptor: 'Bit 0 - 3: fill bits 'Bit 4 : always 0 'Bit 5 : 0 ===> image origin in the lower left corner ' 1 ===> image origin in the upper left corner 'Bit 6 - 7: 00 ===> the image rows are stored one after the other ' 01 ===> first are stored the even rows (0, 2, 4 ...) ' after this are stored the odd rows (1, 3, 5 ...) 'The formula to calculate the length of the DAC table: 'daclength% = colnumber*entrybits/8 'After the 18 bytes of the TGA header is stored the information 'block in the TGA file, but the length of this block is mostly 0. 'After the information block is stored the DAC table and then the 'image datas. '=========================================================================== 'Program starts here. = '=========================================================================== DECLARE SUB Reading (x%, y%) DECLARE SUB Waiting () TYPE tgaheader 'declare the header info AS STRING * 1 'length of image information block colortyp AS STRING * 1 'DAC table or BGR format imagetyp AS STRING * 1 'compressed or uncompressed origin AS INTEGER 'first entry in the DAC table colnumber AS INTEGER 'number of colors in the DAC table entrybits AS STRING * 1 'entry size in the DAC table xvalue AS INTEGER 'x co-ordinate lower left corner yvalue AS INTEGER 'y co-ordinate lower left corner widt AS INTEGER 'image width height AS INTEGER 'image height pixelsize AS STRING * 1 'number of bits per pixel descriptor AS STRING * 1 'image descriptor END TYPE DIM header AS tgaheader 'define the header DIM set%(42) 'machine code array for pixel set procedure setseg% = VARSEG(set%(0)) setoff% = VARPTR(set%(0)) 'start address for pixel set routine DIM text%(4) 'machine code array for text mode procedure textseg% = VARSEG(text%(0)) textoff% = VARPTR(text%(0)) 'start address text mode procedure file$ = "ELENA.TGA" 'change it, if necessary filelength& = 0 'length of the TGA file daclength% = 0 'length of the DAC table numcolors% = 0 'number of used colors dacstart& = 0 'start of the DAC values in the 'TGA file dacend& = 0 'end of the DAC values imstart& = 0 'start of the image data in the 'TGA file CLS RESTORE setpixel CALL Reading(setseg%, setoff%) 'read the machine code (pixel procedure) RESTORE textmode CALL Reading(textseg%, textoff%)'read the machine code (text mode routine) OPEN file$ FOR BINARY AS #1 'open the TGA file filelength& = LOF(1) 'determine the file length GET #1, 1, header 'read the header CLOSE #1 'close the file IF ASC(header.colortyp) <> 1 THEN 'image hasn't a DAC table PRINT PRINT "Sorry! This TGA image hasn't a DAC table." END END IF IF ASC(header.imagetyp) <> 1 THEN 'data must be uncompressed PRINT PRINT "Sorry! This TGA format isn't supported." END END IF daclength% = header.colnumber * ASC(header.entrybits) / 8 'calculate the length of th DAC table numcolors% = daclength% / 3 'calculate the number of used colors dacstart& = 19 + ASC(header.info) 'calculate the DAC start dacend& = dacstart& + daclength% 'calculate the DAC end PRINT PRINT "Information about the image:" PRINT "============================" PRINT PRINT "Number of used colors ="; header.colnumber PRINT "Image width ="; header.widt; "Pixel" PRINT "Image height ="; header.height; "Pixel" PRINT PRINT "Please press any key ..." CALL Waiting CLS 'clear the screen SCREEN 13 'VGA 320 by 200 pixel and 256 colors OPEN file$ FOR BINARY AS #1 'open the TGA file SEEK #1, dacstart& 'start of the DAC table FOR register% = 0 TO 255 'set the DAC registers temp$ = SPACE$(3) 'temporary string GET #1, , temp$ 'read BGR value red% = ASC(MID$(temp$, 3)) \ 4 'we need only 6 Bits green% = ASC(MID$(temp$, 2)) \ 4 blue% = ASC(MID$(temp$, 1)) \ 4 OUT &H3C8, register% 'set register OUT &H3C9, red% 'set the RGB values OUT &H3C9, green% OUT &H3C9, blue% NEXT register% SEEK #1, dacend& 'start of the image data temp$ = SPACE$(1) 'temporary string FOR y% = header.height - 1 TO 0 STEP -1 'row loop FOR x% = 0 TO header.widt - 1 'column loop GET #1, , temp$ 'read 1 color byte col% = ASC(temp$) 'calculate the color value DEF SEG = setseg% 'set the segment CALL ABSOLUTE(x%, y%, col%, setoff%) 'set the pixel DEF SEG 'reset the segment NEXT x% NEXT y% CLOSE #1 'close the file CALL Waiting 'wait for a key DEF SEG = textseg% CALL ABSOLUTE(textoff%) 'set the text mode DEF SEG CLS END setpixel: DATA 55: 'push bp DATA 8B,EC: 'mov bp,sp DATA 06: 'push es DATA 8B,76,08: 'mov si,[bp+8] ;si:=address y% DATA 8B,7E,0A: 'mov di,[bp+10] ;di:=address x% DATA 8B,5E,06: 'mov bx,[bp+6] ;bx:=address col% DATA B8,40,01: 'mov ax,320 ;ax:=320=bytes per row DATA 8B,0C: 'mov cx,[si] ;cx:=y% DATA F7,E1: 'mul cx ;ax:=y%*320 DATA 03,05: 'add ax,[si] ;ax:=y%*320+x% DATA 8B,F8: 'mov di,ax ;di:=ax=offset into video RAM DATA B8,00,A0: 'mov ax,0a000H ;ax:=segment video RAM DATA 8E,C0: 'mov es,ax ;es:di -> pixel position DATA 8B,07: 'mov ax,[bx] ;ax:=col% DATA 26,88,05: 'mov byte ptr es:[di],al ' ;set the pixel DATA 07: 'pop es DATA 8B,E5: 'mov sp,bp DATA 5D: 'pop bp DATA CA,06,00: 'ret 6 DATA *: 'end code textmode: DATA B8,03,00: 'mov ax,0003H ;function: set text mode DATA CD,10: 'int 10H ;transfer to BIOS DATA CB: 'ret DATA *: 'end code SUB Reading (x%, y%) DEF SEG = x% 'set the segment FOR i% = 0 TO 199 'reading loop READ byte$ 'read 1 byte IF byte$ = "*" THEN EXIT FOR 'end code POKE (y% + i%), VAL("&H" + byte$) 'write 1 byte NEXT i% DEF SEG 'reset the segment END SUB SUB Waiting WHILE INKEY$ = "" WEND END SUB