'=========================================================================== ' Subject: OPENBMP VERSION 0.3 Date: 11-01-98 (05:17) ' Author: Yousuf Philips Code: QB, QBasic, PDS ' Origin: philipz@emirates.net.ae Packet: GRAPHICS.ABC '=========================================================================== '''''''''''''''''''''''''''''''''''''''' ' Program : Loads BMP Files ' ' Name : OPENBMP Version 0.3 ' ' Programmer : Yousuf Philips ' ' Company : Y P I ' ' Updated On : 12th of Sept. 1998 ' ' Email - [philipz85@hotmail.com] ' ' [http://members.xoom.com/Philipz/] ' '''''''''''''''''''''''''''''''''''''''' '/* Do not edit this file if you distribute it. */' '/* (c) Copyrighted by YPI in 1998 | All Rights Reserved | Public Domain */' '/* This program has been created by YPI (Basic Programming Incorporation) */' '/* as a utility to load BMP files. Aaron Zabudsky is the first programmer */' '/* to load BMP files in BASIC and his loader is known as SHOWBMP.BAS. I */' '/* have been in contact with him and have to say that his commenting in */' '/* SHOWBMP.BAS of the BMP file format was excellent and simple. I would */' '/* like to give credit and special thanks to him. This loader was created */' '/* to load all Windows BMPs and is fast in loading compressed BMPs. */' '/* This BMP loader is part of a series of BMP loaders which have been */' '/* created by YPI. The source code for version 0.1 and 0.2 haven't been */' '/* distributed and won't because this version (0.3) is many times faster */' '/* and is able to load all Windows BMPs but if you really want, just ask. */' '/* If you use any of this code in your program then you must credit YPI */' '/* and also Aaron Zabudsky. This program has been placed in Public Domain */' '/* and All Rights Are Reserved. */' '/* YPI has also created a PCX loader and an FLI player. The source can be */' '/* gotten from our website */' '/* The YPI Website has programs for beginners, tutorials and utilities. */' '/* Aaron Zabudsky's email is */' DECLARE SUB BMPInfo (FileName$) DECLARE SUB SHOWBMP (FileName$) DIM SHARED X, Y AS INTEGER CLS PRINT PRINT " Fast BMP Loader for QBASIC - By YPI (BASIC Programming Incorporation)" 'FILES "*.bmp" INPUT " Enter File Name - ", FileName$ IF LEN(LTRIM$(FileName$)) = 0 THEN END ELSEIF INSTR(FileName$, ".") = 0 THEN FileName$ = FileName$ + ".bmp" END IF CALL BMPInfo(FileName$) Wait$ = INPUT$(1) CALL SHOWBMP(FileName$) Wait$ = INPUT$(1) SUB BMPInfo (FileName$) '/* Opens the specified File Name */' OPEN FileName$ FOR BINARY AS #1 '/* If the file name specified is empty then a line of text is printed, */' '/* the file is then deleted and the program ends */' IF LOF(1) = 0 THEN PRINT " FILE IS EMPTY" CLOSE #1 KILL FileName$ EXIT SUB END IF CLS '/* Extracts the first 2 bytes of the file */' ValidBMP$ = SPACE$(2) GET #1, 1, ValidBMP$: PRINT IF ValidBMP$ = "BM" THEN PRINT " Valid BMP FILE" ELSE PRINT " InValid BMP FILE" END IF '/* Extracts the Size of the file without the header */' SizeOfFile$ = SPACE$(4) GET #1, 3, SizeOfFile$ PRINT " Size of the file -"; CVL(SizeOfFile$); " or "; LOF(1) '/* Extracts the offset of the picture data in the file */' LocationOfPictureData$ = SPACE$(4) GET #1, 11, LocationOfPictureData$ PRINT " Location in file of Picture Data -"; CVL(LocationOfPictureData$) '/* Extracts the BMP type (Win or OS/2) */' BMPType$ = SPACE$(4) GET #1, 15, BMPType$ PRINT : PRINT " BMP Type - "; IF CVL(BMPType$) = 12 THEN PRINT "OS/2" PRINT " Size Of Header - 12" ELSEIF CVL(BMPType$) = 40 THEN PRINT "Windows" PRINT " Size Of Header - 40" ELSE PRINT "Unknown Type" END IF '/* Extracts the Width and Height in Pixels of the Image */' '/* and also the number of bits per pixel (bpp) */' PixelWidth$ = SPACE$(4): PixelHeight$ = SPACE$(4) BitsPerPixel$ = SPACE$(2): NoPlanes$ = SPACE$(2): Compress$ = SPACE$(4) GET #1, 19, PixelWidth$ GET #1, 23, PixelHeight$ GET #1, 27, NoPlanes$ GET #1, 29, BitsPerPixel$ GET #1, 31, Compress$ PRINT PRINT " Width of Image in Pixels -"; CVL(PixelWidth$) PRINT " Height of Image in Pixels -"; CVL(PixelHeight$) PRINT " Number of Planes -"; CVI(NoPlanes$) PRINT " Number of Bits Per Pixel (bpp) -"; CVI(BitsPerPixel$) PRINT " Number of Colors Used in the Image -"; 2 ^ CVI(BitsPerPixel$) IF CVL(Compress$) = 0 THEN PRINT " No Compression" ELSEIF CVL(Compress$) = 1 THEN PRINT " RLE - 8-Bit Compression" ELSEIF CVL(Compress$) = 2 THEN PRINT " RLE - 4-Bit Compression" END IF CLOSE END SUB SUB SHOWBMP (FileName$) OPEN FileName$ FOR BINARY AS #1 IF LOF(1) = 0 THEN PRINT " FILE IS EMPTY" CLOSE #255 KILL FileName$ EXIT SUB END IF '/* Extracts the first 2 bytes of the file */' ValidBMP$ = SPACE$(2) GET #1, 1, ValidBMP$ '/* If the first 2 bytes of the file are not BM then a line of text is printed, */' '/* and the program ends */' IF ValidBMP$ <> "BM" THEN PRINT " THE FILE SPECIFIED IS NOT A VALID BMP" EXIT SUB END IF '/* Extracts the offset of the picture data in the file */' LocationOfPictureData$ = SPACE$(4) GET #1, 11, LocationOfPictureData$ LocationOfPictureData = CVL(LocationOfPictureData$) '/* Extracts the BMP type (Win or OS/2) */' BMPType$ = SPACE$(4) GET #1, 15, BMPType$ '/* If the BMPType is for OS/2 then the a line of text is printed, then */' '/* program ends */' IF CVL(BMPType$) = 12 OR CVL(BMPType$) = 64 THEN PRINT " THIS BMP IS FOR THE OS/2 AND CAN'T BE OPENED IN THIS VERSION OF OPENBMP" PRINT " PLEASE SEND ANY OS/2 BMP TO phililpz85@hotmail.com" PRINT " BY SENDING OS/2 BMP's TO US, WE WILL HOPEFULLY BE ABLE TO OPEN THEM IN THE" PRINT " NEXT VERSION OF OPENBMP" EXIT SUB END IF '/* Extracts the Width and Height in Pixels of the Image */' '/* and also the number of bits per pixel (bpp) */' PixelWidth$ = SPACE$(4) PixelHeight$ = SPACE$(4) BitsPerPixel$ = SPACE$(2) Compression$ = SPACE$(4) GET #1, 19, PixelWidth$ GET #1, 23, PixelHeight$ GET #1, 29, BitsPerPixel$ GET #1, 31, Compression$ PixelWidth = CVL(PixelWidth$) PixelHeight = CVL(PixelHeight$) BitsPerPixel = CVI(BitsPerPixel$) NumberOfColors = 2 ^ BitsPerPixel '/* Changing to suitable screen modes to display the Image */' IF BitsPerPixel = 1 THEN IF PixelWidth > 640 OR PixelHeight > 480 THEN PRINT " 1-BIT IMAGE IS TO LARGE" EXIT SUB END IF SCREEN 11 ELSEIF BitsPerPixel = 4 THEN SCREEN 12 ELSEIF BitsPerPixel = 8 THEN SCREEN 13 END IF '/* If image is not 24-bit then load palette information from file */' IF BitsPerPixel <> 24 THEN '/* Extracts Palette information for the colors used in the image */' PaletteColors$ = SPACE$(NumberOfColors * 4) GET #1, 55, PaletteColors$ FOR Loops = 0 TO NumberOfColors - 1 '/* Changes the Palette of each color to the one specified in the file */' IF BitsPerPixel = 1 AND Loops = 1 THEN Loops = 15 OUT &H3C8, Loops IF BitsPerPixel = 1 AND Loops = 15 THEN Loops = 1 OUT &H3C9, ASC(MID$(PaletteColors$, Loops * 4 + 3, 1)) \ 4 'Red OUT &H3C9, ASC(MID$(PaletteColors$, Loops * 4 + 2, 1)) \ 4 'Green OUT &H3C9, ASC(MID$(PaletteColors$, Loops * 4 + 1, 1)) \ 4 'Blue NEXT Loops '/* Finds correct location of Picture data */' IF LocationOfPictureData = 0 THEN LocationOfPictureData = LOC(255) + 1 ELSE LocationOfPictureData = LocationOfPictureData + 1 END IF END IF IF BitsPerPixel = 24 THEN SCREEN 13 PaletteBlue$ = SPACE$(1): PaletteGreen$ = SPACE$(1): PaletteRed$ = SPACE$(1) SEEK #1, LocationOfPictureData FOR Loops = 0 TO 255 OUT &H3C8, Loops OUT &H3C9, Loops \ 4 OUT &H3C9, Loops \ 4 OUT &H3C9, Loops \ 4 NEXT Loops ActualWidth = PixelWidth / 320: ActualHeight = PixelHeight / 200 IF ActualWidth < 1 THEN ActualWidth = 1 IF ActualHeight < 1 THEN ActualHeight = 1 IF (4 - ((PixelWidth * 3) MOD 4)) = 4 THEN LineExtract$ = SPACE$(PixelWidth * 3) ELSE LineExtract$ = SPACE$((PixelWidth * 3) + (4 - ((PixelWidth * 3) MOD 4))) END IF IF ActualWidth = 1 AND ActualHeight = 1 THEN FOR Y = PixelHeight - 1 TO 0 STEP -1 GET #1, , LineExtract$ FOR X = 0 TO PixelWidth - 1 PaletteBlue$ = MID$(LineExtract$, X * 3 + 1, 1) PSET (X, Y), ASC(PaletteBlue$) NEXT X NEXT Y ELSE FOR Y = PixelHeight - 1 TO 0 STEP -1 GET #1, , LineExtract$ FOR X = 0 TO PixelWidth - 1 PaletteBlue$ = MID$(LineExtract$, X * 3 + 1, 1) PSET (X / ActualWidth, Y / ActualHeight), ASC(PaletteBlue$) NEXT X NEXT Y END IF EXIT SUB ELSEIF CVL(Compression$) = 1 THEN PixelColors$ = SPACE$(1): NoOfSameColors$ = SPACE$(1) RightMovement$ = SPACE$(1): UpMovement$ = SPACE$(1) ActualWidth = PixelWidth / 320: ActualHeight = PixelHeight / 200 IF ActualWidth < 1 THEN ActualWidth = 1 IF ActualHeight < 1 THEN ActualHeight = 1 X = 0: Y = PixelHeight - 1 DO GET #1, , NoOfSameColors$ IF ASC(NoOfSameColors$) <> 0 THEN GET #1, , PixelColors$ IF X + ASC(NoOfSameColors$) = PixelWidth THEN NoOfSameColors$ = CHR$(ASC(NoOfSameColors$) - 1) LINE (X / ActualWidth, Y / ActualHeight)-STEP(ASC(NoOfSameColors$) / ActualWidth, 0), ASC(PixelColors$) X = X + ASC(NoOfSameColors$) ELSE GET #1, , PixelColors$ IF ASC(PixelColors$) = 0 THEN X = 0: Y = Y - 1 IF Y < 0 THEN EXIT SUB '/* Used to skip the unnecessary lines in large pictures WHILE Y MOD ActualHeight <> 0 DO GET #1, , NoOfSameColors$ IF ASC(NoOfSameColors$) <> 0 THEN GET #1, , PixelColors$ ELSE GET #1, , PixelColors$ IF ASC(PixelColors$) = 0 THEN EXIT DO ELSEIF ASC(PixelColors$) = 1 THEN EXIT SUB ELSEIF ASC(PixelColors$) = 2 THEN Bytez$ = SPACE$(2) GET #1, , Bytez$ EXIT DO ELSE Bytez$ = SPACE$(ASC(PixelColors$)) IF ASC(PixelColors$) MOD 2 = 1 THEN Bytez$ = Bytez$ + " " GET #1, , Bytez$ END IF END IF LOOP Y = Y - 1 WEND ELSEIF ASC(PixelColors$) = 1 THEN EXIT DO ELSEIF ASC(PixelColors$) = 2 THEN GET #1, , RightMovement$ GET #1, , UpMovement$ X = X + ASC(RightMovement$): Y = Y + ASC(UpMovement$) ELSE PixelColor$ = SPACE$(1) FOR Loops = 1 TO ASC(PixelColors$) GET #1, , PixelColor$ PSET (X / ActualWidth, Y / ActualHeight), ASC(PixelColor$) X = X + 1 NEXT Loops IF ASC(PixelColors$) MOD 2 = 1 THEN GET #1, , PixelColor$ END IF END IF LOOP EXIT SUB ELSEIF CVL(Compression$) = 2 THEN PixelColors$ = SPACE$(1): NoOfSameColors$ = SPACE$(1) RightMovement$ = SPACE$(1): UpMovement$ = SPACE$(1) ActualWidth = PixelWidth / 640: ActualHeight = PixelHeight / 480 IF ActualWidth < 1 THEN ActualWidth = 1 IF ActualHeight < 1 THEN ActualHeight = 1 X = 0: Y = PixelHeight - 1 DO GET #1, , NoOfSameColors$ IF ASC(NoOfSameColors$) <> 0 THEN GET #1, , PixelColors$ FOR Loops = 0 TO ASC(NoOfSameColors$) - 1 STEP 2 PSET (X / ActualWidth, Y / ActualHeight), ASC(PixelColors$) \ 16 X = X + 1 IF Loops + 1 <> ASC(NoOfSameColors$) THEN PSET (X / ActualWidth, Y / ActualHeight), ASC(PixelColors$) AND 15 X = X + 1 END IF NEXT Loops ELSE GET #1, , PixelColors$ IF ASC(PixelColors$) = 0 THEN X = 0: Y = Y - 1 IF Y < 0 THEN EXIT SUB '/* Used to skip the unnecessary lines in large pictures WHILE Y MOD ActualHeight <> 0 DO GET #1, , NoOfSameColors$ IF ASC(NoOfSameColors$) <> 0 THEN GET #1, , PixelColors$ ELSE GET #1, , PixelColors$ IF ASC(PixelColors$) = 0 THEN EXIT DO ELSEIF ASC(PixelColors$) = 1 THEN EXIT SUB ELSEIF ASC(PixelColors$) = 2 THEN Bytez$ = SPACE$(2) GET #1, , Bytez$ EXIT DO ELSE PixelColors = ASC(PixelColors$) IF PixelColors MOD 2 = 1 THEN PixelColors = PixelColors + 1 END IF PixelColors = PixelColors / 2 IF PixelColors MOD 2 = 1 THEN PixelColors = PixelColors + 1 END IF Bytez$ = SPACE$(PixelColors) GET #1, , Bytez$ END IF END IF LOOP Y = Y - 1 WEND ELSEIF ASC(PixelColors$) = 1 THEN EXIT DO ELSEIF ASC(PixelColors$) = 2 THEN GET #1, , RightMovement$ GET #1, , UpMovement$ X = X + ASC(RightMovement$): Y = Y + ASC(UpMovement$) ELSE PixelColor$ = SPACE$(1): PixelColors = ASC(PixelColors$) FOR Loops = 0 TO PixelColors - 1 IF Loops MOD 2 = 0 THEN GET #1, , PixelColor$ PSET (X / ActualWidth, Y / ActualHeight), ASC(PixelColor$) \ 16 X = X + 1 END IF IF Loops MOD 2 = 1 THEN PSET (X / ActualWidth, Y / ActualHeight), ASC(PixelColor$) AND 15 X = X + 1 END IF NEXT Loops IF PixelColors MOD 2 = 1 THEN PixelColors = PixelColors + 1 END IF NoOfBytes = PixelColors / 2 IF (NoOfBytes MOD 2) = 1 THEN GET #1, , PixelColor$ END IF END IF END IF LOOP EXIT SUB END IF IF BitsPerPixel = 8 THEN LineExtract = (INT((PixelWidth - 1) / 4) + 1) * 4 LineExtract$ = SPACE$(LineExtract) ActualWidth = PixelWidth / 320 ActualHeight = PixelHeight / 200 IF ActualHeight <= 1 AND ActualWidth <= 1 THEN FOR Y = 0 TO PixelHeight - 1 GET #1, 1079 + ((PixelHeight - 1) * LineExtract) - (Y * LineExtract), LineExtract$ FOR X = 0 TO PixelWidth - 1 PSET (X, Y), ASC(MID$(LineExtract$, X + 1, 1)) NEXT X NEXT Y ELSE FOR Y = 0 TO PixelHeight - 1 STEP ActualHeight GET #1, LocationOfPictureData + ((LineExtract * (PixelHeight - 1)) - (LineExtract * Y)), LineExtract$ FOR X = 0 TO PixelWidth - 1 STEP ActualWidth PSET (X / ActualWidth, Y / ActualHeight), ASC(MID$(LineExtract$, X + 1, 1)) NEXT X NEXT Y END IF ELSEIF BitsPerPixel = 4 THEN LineExtract = (INT((PixelWidth - 1) / 8) + 1) * 4 LineExtract$ = SPACE$(LineExtract) ActualWidth = PixelWidth / 640 ActualHeight = PixelHeight / 480 IF ActualWidth <= 1 AND ActualHeight <= 1 THEN FOR Y = 0 TO PixelHeight - 1 GET #1, LocationOfPictureData + ((LineExtract * (PixelHeight - 1)) - (LineExtract * Y)), LineExtract$ FOR X = 0 TO (PixelWidth / 2) - 1 PixelColor = ASC(MID$(LineExtract$, X + 1, 1)) PSET (X * 2, Y), PixelColor \ 16 IF (X * 2) + 1 < PixelWidth THEN PSET ((X * 2) + 1, Y), PixelColor AND 15 END IF NEXT X NEXT Y ELSE FOR Y = 0 TO PixelHeight - 1 STEP ActualHeight GET #1, LocationOfPictureData + ((LineExtract * (PixelHeight - 1)) - (LineExtract * Y)), LineExtract$ FOR X = 0 TO (PixelWidth / 2) - 1 PixelColor = ASC(MID$(LineExtract$, X + 1, 1)) PSET (X / ActualWidth, Y / ActualHeight), PixelColor \ 16 IF (X * 2) + 1 < PixelWidth THEN PSET ((X + 1) / ActualWidth, Y / ActualHeight), PixelColor AND 15 END IF NEXT X NEXT Y END IF ELSEIF BitsPerPixel = 1 THEN LineExtract = (INT((PixelWidth - 1) / 32) + 1) * 4 LineExtract$ = SPACE$(LineExtract) FOR Y = 0 TO PixelHeight - 1 DEF SEG = &HA000 GET #1, LocationOfPictureData + ((PixelHeight - 1) * LineExtract) - (Y * LineExtract), LineExtract$ FOR X = 0 TO CINT(PixelWidth / 8) - 1 IF Y < 409 THEN POKE (Y * 80 + X), ASC(MID$(LineExtract$, X + 1, 1)) ELSE DEF SEG = &HA7D0 POKE ((Y - 400) * 80 + X), ASC(MID$(LineExtract$, X + 1, 1)) END IF NEXT X NEXT Y DEF SEG END IF END SUB