Welcome to oscc.kr

 qbasic - bmp 처리방법
2019-12-20 10:50:49
Hit : 287, Vote : 69

작성자 : 피시키드

출처 : http://www.petesqbsite.com/sections/tutorials/tuts/loading_bmps.html

Loading BMP files in QBasic

Here I will give you the general format of a .bmp image file and outline the steps needed to load and display one on the screen. Although there are many libraries that will do this for you, it's nice to write your own code and one day, you might be writing your own library =).

BMP images are actualy one of the simplest image formats as there is no compression involved.
The header is 1078 bytes long and contains vital elements such as image dimensions, colour depth and the actual palette. Following is a QBasic TYPE structure that we can use to load the image in one go:

TYPE BMPHeaderType       
        id AS STRING * 2      'Should be "BM"
        size AS LONG          'Size of the data
        rr1 AS INTEGER        '
        rr2 AS INTEGER        '
        offset AS LONG        'Position of start of pixel data
        horz AS LONG          '
        wid AS LONG           'Image width
        hei AS LONG           'Image height
        planes AS INTEGER     '
        bpp AS INTEGER        'Should read 8 for a 256 colour image
        pakbyte AS LONG       '
        imagebytes AS LONG    'Width*Height
        xres AS LONG          '
        yres AS LONG          '
        colch AS LONG         '
        ic AS LONG            '
        pal AS STRING * 1024  'Stored as <Blue, Green, Red, 0>

I've commented the important fields. We can use these to verify the contents of the file. Now to grab the header, all we need to do is DIM an instance of this structure, open the file and read the data. We open the file in BINARY mode so we can access the file data directly. We'll use a made-up BMP file called "demo.bmp". Here's the code:

DIM BmpHeader AS BMPHeaderType

OPEN "demo.bmp" FOR BINARY AS #1

  GET #1, , BmpHeader

' Don't close the file just yet - we're not finished!

Now we have all the data we need to load the image. From here, the rest of the file just contains the pixel data. After the GET, the file pointer is moved to the first pixel. But before we start displaying anything, we should change our current palette to the one given in our image file. The palette is stored in our header as 256 DWords (4 bytes). For each colour, 3 bytes contain the RGB palette values, while the 4th is just used for padding and is set to zero. Here's how to set the palette:

SCREEN 13					    ' Set graphics mode

a$ = BmpHeader.pal                                  ' Pal is stored in a 1024 character string

OUT &H3C8, 0					    ' Start writing from Colour 0
FOR I% = 1 TO 1024 STEP 4
        b% = ASC(MID$(a$, I%, 1)) \ 4      'blue
        g% = ASC(MID$(a$, I% + 1, 1)) \ 4  'green
        r% = ASC(MID$(a$, I% + 2, 1)) \ 4  'red
						    ' I% + 3 is set to zero.
        OUT &H3C9, r%				    ' Set the colour.
        OUT &H3C9, g%
        OUT &H3C9, b%

Now we're ready to show something! What we do is, create two FOR .. NEXT (x and y) which extend to the dimensions of our image. Now the very weird thing here is, the image is actually stored in the file upside down! I don't know why they chose to do this, but we have to modify our Y loop to count backwards instead. Each pixel consumes exactly one byte, so this is how we read it. Unfotunately, QBasic does not have a Byte-sized (excuse the pun ;) variable. So we improvise and DIM a string of size 1, this also holds one byte. Here's the code ..

DIM Pixel AS STRING * 1                  ' Our pixel "byte".

iHeight% = BmpHeader.hei - 1             ' Subtract 1 for actual screen position
iWidth% = BmpHeader.wid - 1              '

FOR y% = iHeight% TO 0 STEP -1           ' Countdown for upsidedown image
FOR x% = 0 TO iWidth%

GET #1, , Pixel         ' read pixel     ' Read one pixel (byte)
PSET (x%, y%), ASC(Pixel)                ' Pixel is actually a string so we get the pixel 
					 ' number by requesting the "ASC" value
NEXT x%, y%


That's it! Unless your image is bigger than 320x200, you will have your BMP image on-screen.


Making it faster

Unless you have a really fast computer (greater than 400Mhz) you will be unsatisfied by the speed in which the image loaded. There are a couple of optimisations we can apply here.


  1. Intead of reading one byte at a time, read BmpHeader.wid bytes and load a line at a time
  2. We can do a memcopy from our pixel buffer to display memory instead of PSETting.

The first one is easy. We simply create a string of size BmpHeader.wid bytes. We can't do the familiar DIM statement this time, as QBasic only allows constants in that declaration. Still, we have a workaround. All we do is set a string to a specified number of SPACE$() Here's a direct replacement of the previous code:

Pixel$ = SPACE$(bmpheader.wid)

iHeight% = bmpheader.hei - 1
iWidth% = bmpheader.wid - 1

FOR y% = iHeight% TO 0 STEP -1

GET #1, , Pixel$				 ' Reads an entire line at once

FOR x% = 0 TO iWidth%
  PSET (x%, y%), ASC(MID$(Pixel$, x% + 1, 1))



I timed this new function against the old one and it was nearly 8 times the speed. Better eh? This should tell you about the speed of data transfer from disk =).

Now the second optimisation isn't as easy. What we do is use an Interrupt. If you don't know what this is, then search elsewhere on this site for my tutorial on it (plug, plug ;). The interrupt we'll use is the DOS interrupt (&H21) and Sub-Function 3Fh (Read from file or device). What we do is pass the interrupt a memory address (in this case, some location on the screen) and the number of bytes to read. I wont cover the code here, as it means a complete re-write. Check my tutorial on interrupts, I give an example of loading a BMP image there.


  USB 표면저항 값 알아내기 
12 0 2020/07/06
  커스타드 크림 제조 
638 64 2019/12/23
  qbasic - bmp 처리방법 
287 69 2019/12/20
  리모콘에 쓰이는 부품중 이게 뭐예요? 
308 72 2019/12/19
  buddy 3.0 정품등록 -oilman.new21.net 
374 81 2019/11/19
  아두이노 키지판 3핀 
351 81 2019/11/11
  파일리스 공격   1
376 86 2019/11/08
  자바소스 난독화 
462 92 2019/10/21
  제로보드4 파일 다운로드부분   1
606 103 2019/10/15
  sketch for ppt 
5196 116 2019/10/14
  html 태그 (zb4, zeroboard4) 용 허용 태그 (with mysql query)  
1116 110 2019/10/07
  Windows Remote Desktop on GPU (윈도우 원격데스크톱 연결로 GPU활성화) 
1300 114 2019/10/01
비밀글입니다  통학버스 관련 카카오톡 봇 개발할것   1
9 0 2019/09/27
  MFM하드 PDF 링크 
499 107 2019/09/24
  minecraft 서버 로그 검색 
453 117 2019/09/22
  와콤 태블릿 호환표 
571 110 2019/09/17
비밀글입니다  ... 
3 0 2019/09/11
  오류코드 통합정리 php   1
474 125 2019/09/10
  lvm - lv 확장하기 
585 131 2019/07/31
  lvm #1 -- 100% 용량 전부 쓰고 싶으면 
580 131 2019/07/31
  linux boot 손상될때 
642 132 2019/07/31
비밀글입니다  정리노트-안드로이드 프로그래밍  
5 0 2018/10/17
1012 237 2018/10/16
  파일 내부 문자열 교체 (find,perl) 
1508 243 2018/10/15
  HP 200LX 구매하고 싶습니다.   1
6705 389 2018/04/30
비밀글입니다  aps  
6 0 2018/03/05
  phpmyadmin #1698 
2211 436 2018/02/21
  리눅스에서 vino 설정시... 
2806 589 2016/01/14
  프로텍 as 
4183 600 2014/04/07
4136 585 2014/01/28

1 [2][3]

Copyright (C) 1997-2020 All Rights Reserved.