Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: QB: BMP-kuvan näyttäminen

Sivun loppuun

Antti Laaksonen [30.05.2003 01:38:22]

#

Tämä ohjelma näyttää 2-, 16- ja 256-värisiä BMP-kuvia QBasicissa käyttäen grafiikkatilaa 13 (320x200 tarkkuus, 256 väriä). Se lukee kuvan rakenteen, paletin ja pikselit tiedostosta ja piirtää kuvan näiden tietojen perusteella. Kuvan piirtämiseen on kohdistettu pientä optimointia, ja se tuntuukin olevan verrattain nopea.

BMP-kuvan rakenteesta sen verran, että tiedoston alussa on kaksi kuvan rakenteen sisältävää tietuetta: BITMAPFILEHEADER ja BITMAPINFOHEADER. Jälkimmäinen sisältää tärkeimmät tiedot, mm. kuvan leveyden ja korkeuden sekä värimäärän. Tämän jälkeen tulee paletti nelitavuisena RGBQUAD-tietueena ja lopuksi itse kuvadata, jonka muoto riippuu värien määrästä. Kuva luetaan vasemmalta oikealle ja alhaalta ylös; ensimmäinen pikseli on siis vasen alanurkka ja viimeinen oikea ylänurkka.

1-bittiset eli 2-väriset eli mustavalkoiset kuvat: Paletissa on kaksi väriä ja yhdessä tavussa on kahdeksan pikseliä (bitti per pikseli).

4-bittiset eli 16-väriset kuvat: Paletissa on kuusitoista väriä ja yhdessä tavussa on kaksi pikseliä.

8-bittiset eli 256-väriset kuvat: Paletissa on 256 väriä ja yhdessä tavussa on yksi pikseli.

Ohjelma EI osaa näyttää 24-bittisiä kuvia (ei mahdollista VGA-tilassa) eikä RLE-pakattuja kuvia (harvinainen pakkaus - koodista olisi tullut entistäkin sekavampi).

'**************************************************************
'* Ohjelma lukee ja näyttää 2-, 16- ja 256-värisiä BMP-kuvia. *
'*                                                            *
'* Tekijä: Antti Laaksonen (antti.laaksonen@mbnet.fi)         *
'**************************************************************

DIM kuva AS STRING
kuva = "c:\antti\320200.bmp" 'näytettävä kuva

DEFINT A-Z

TYPE BITMAPFILEHEADER
  bfType AS STRING * 2
  bfSize AS LONG
  bfReserved1 AS INTEGER
  bfReserved2 AS INTEGER
  bfOffBits AS LONG
END TYPE

TYPE BITMAPINFOHEADER
  biSize AS LONG
  biWidth AS LONG
  biHeight AS LONG
  biPlanes AS INTEGER
  biBitCount AS INTEGER
  biCompression AS LONG
  biSizeImage AS LONG
  biXPelsPerMeter AS LONG
  biYPelsPerMeter AS LONG
  biClrUsed AS LONG
  biClrImportant AS LONG
END TYPE

TYPE RGBQUAD
  rgbBlue AS STRING * 1
  rgbGreen AS STRING * 1
  rgbRed AS STRING * 1
  rgbReserved AS STRING * 1
END TYPE

CONST BIRGB = 0&
CONST BIRLE8 = 1&
CONST BIRLE4 = 2&

DIM tiedosto AS BITMAPFILEHEADER
DIM info AS BITMAPINFOHEADER
DIM vari AS RGBQUAD

IF DIR$(kuva) = "" THEN
  PRINT "Tiedostoa ei löytynyt!"
  END
END IF

OPEN kuva FOR BINARY AS #1

GET #1, , tiedosto
GET #1, , info

SCREEN 13

IF tiedosto.bfType <> "BM" THEN
  PRINT "Tuntematon tiedostomuoto!"
  END
END IF

DIM pikseli AS STRING, kohta AS LONG, tase AS STRING * 1
DEF SEG = &HA000
kohta = 320& * info.biHeight - 1
merkki = 0

SELECT CASE info.biBitCount
CASE 1
  OUT &H3C8, 0
  FOR i = 1 TO 2
    GET #1, , vari
    OUT &H3C9, ASC(vari.rgbRed) \ 4
    OUT &H3C9, ASC(vari.rgbGreen) \ 4
    OUT &H3C9, ASC(vari.rgbBlue) \ 4
  NEXT
  leveys = INT(info.biWidth / 8 + .5)
  pikseli = SPACE$(leveys)
  GET #1, , pikseli
  loppu& = info.biHeight * leveys
  miinus = info.biWidth MOD 8
  SELECT CASE leveys MOD 4
  CASE 0: v = -1: CASE 1: v = 2: CASE 2: v = 1: CASE 3: v = 0
  END SELECT
  FOR i& = 1 TO loppu&
    merkki = merkki + 1
    IF kohta < 64000 THEN
      tavu = ASC(MID$(pikseli, merkki, 1))
      FOR j = 0 TO 7
        POKE kohta + 7 - j, SGN(tavu AND 2 ^ j)
      NEXT
    END IF
    kohta = kohta + 8
    IF i& MOD leveys = 0 THEN
      kohta = kohta - 320 - info.biWidth + miinus
      FOR j = 0 TO v: GET #1, , tase: NEXT
      GET #1, , pikseli
      merkki = 0
    END IF
  NEXT
CASE 4
  OUT &H3C8, 0
  FOR i = 1 TO 16
    GET #1, , vari
    OUT &H3C9, ASC(vari.rgbRed) \ 4
    OUT &H3C9, ASC(vari.rgbGreen) \ 4
    OUT &H3C9, ASC(vari.rgbBlue) \ 4
  NEXT
  SELECT CASE info.biCompression
  CASE BIRGB
    leveys = INT(info.biWidth / 2 + .5)
    pikseli = SPACE$(leveys)
    GET #1, , pikseli
    loppu& = info.biHeight * leveys
    SELECT CASE leveys MOD 4
    CASE 0: v = -1: CASE 1: v = 2: CASE 2: v = 1: CASE 3: v = 0
    END SELECT
    IF info.biWidth / 2 <> info.biWidth \ 2 THEN miinus = -1
    FOR i& = 1 TO loppu&
      merkki = merkki + 1
      IF kohta < 64000 THEN
        POKE kohta, (ASC(MID$(pikseli, merkki, 1)) \ 16) AND 15
        IF merkki < leveys THEN
          POKE kohta + 1, ASC(MID$(pikseli, merkki, 1)) AND 15
        END IF
      END IF
      kohta = kohta + 2
      IF i& MOD leveys = 0 THEN
        kohta = kohta - 320 - info.biWidth + miinus
        FOR j = 0 TO v: GET #1, , tase: NEXT
        GET #1, , pikseli
        merkki = 0
      END IF
    NEXT
  CASE ELSE
    PRINT "Tuntematon pakkausmuoto!"
  END SELECT
CASE 8
  OUT &H3C8, 0
  FOR i = 1 TO 256
    GET #1, , vari
    OUT &H3C9, ASC(vari.rgbRed) \ 4
    OUT &H3C9, ASC(vari.rgbGreen) \ 4
    OUT &H3C9, ASC(vari.rgbBlue) \ 4
  NEXT
  SELECT CASE info.biCompression
  CASE BIRGB
    pikseli = SPACE$(info.biWidth)
    GET #1, , pikseli
    loppu& = info.biHeight * info.biWidth
    SELECT CASE info.biWidth MOD 4
    CASE 0: v = -1: CASE 1: v = 2: CASE 2: v = 1: CASE 3: v = 0
    END SELECT
    FOR i& = 1 TO loppu&
      kohta = kohta + 1
      merkki = merkki + 1
      IF kohta < 64000 THEN
        POKE kohta, ASC(MID$(pikseli, merkki, 1))
      END IF
      IF i& MOD info.biWidth = 0 THEN
        kohta = kohta - 320 - info.biWidth
        FOR j = 0 TO v: GET #1, , tase: NEXT
        GET #1, , pikseli
        merkki = 0
      END IF
    NEXT
  CASE ELSE
    PRINT "Tuntematon pakkausmuoto!"
  END SELECT
CASE ELSE
  PRINT "Tuntematon värimäärä!"
END SELECT

CLOSE #1

juhaz [30.05.2003 05:52:42]

#

Ei näy ei....
Pelkkä musta tausta näkyy, mutta ei viivaa oikeassa yläkulmassa.

juhaz [30.05.2003 05:56:04]

#

Ahaa kyllähän tuo toimiikin, kun vaan muistaisi tallentaa kuvan :D

Gwaur [30.05.2003 11:52:47]

#

Jee, tämmöstä mä oon aaaaainaa halunnu! :)

T.M. [30.05.2003 11:57:37]

#

hyvin toimii ilman tätä pätkää:

IF DIR$(kuva) = "" THEN
  PRINT "Tiedostoa ei löytynyt!"
  END
END IF

thefox [30.05.2003 13:09:53]

#

Toiminee, ja siistiä koodia (vrt. meikäläisen QB-FLI-playeri ;-) Tuon tosin olisi voinut iskeä funktioksi niin käyttö olisi hieman helpottunut.

Ja vielä tästä rivistä:

POKE kohta + 7 - j, SGN(tavu AND 2 ^ j)

Potenssin (^) käyttäminen on todella hidasta (varsinkin vanhemilla koneilla), veikkaan että simppeli looppi tuon laskemiseen olisi jopa nopeampi...

Gwaur [30.05.2003 15:40:06]

#

Ajoin tämä koodin Ms-Dosissa (ei windowsia alla), ja sitten se väitti että sitä kuvaa ei löydy, vaikka se löytyy oikeasti.
Windowsin alla tämä toimii vallan mainiosti.
Mikähän vikana?

ja16 [30.05.2003 17:04:50]

#

mä jo luulin että osaan qbasiccia kunnolla=) tai quick basiccia!!!!

Sami [31.05.2003 12:00:08]

#

Ei tajua...
Siis näitä kuvien lukemisia.

Lanahard [04.06.2003 19:42:17]

#

Onpas ihme viritys.

kala [06.06.2003 17:04:29]

#

No eipä tollasella kyllä mitään tee jos ei edes RLE-kuvia osaa purkaa. Se RLE pakattu BMP on kyllä yleinen.

24-bittisten kuvien poisjättämisen ymmärtää toki, vaikka nekin voisi ihan hyvin näyttää kvantisoimalla kuvan värejä varten oman paletin.

RLE pakkauksen purkaminen on aika yksinkertaista eikä sellaisen sorsa mikään kovin sekava ole.

Mitä tekee codecilla joka osaa ladata vain murto-osan tiedostoformaatin kuvista??

InvalidCo [07.06.2003 18:14:23]

#

Ei toimi jostain syystä! (Ehkä muokkailujeni syytä)

-The PC-Master-

Skrible [06.07.2003 13:32:05]

#

Ei taho toimia mullakaan...

polestar [25.08.2003 21:04:03]

#

Muistitteko tallentaa kuvan oikeaan hakemistoon oikealla nimellä? Tallensin oman kuvan 256-värisenä ja toimi hyvin.

Turha ruveta mitään 24-bittisiä värejä väsäämään. QBasikin käyttäjille riittää useimmissa tapauksissa myös 256 väriä.

maratti [01.10.2003 20:20:08]

#

Miten saan niin että se kuva pitää olla samassa hakemistossa kun itse ohjelma tai toi systeemi? Ettei sille tartte aina erikseen kertoa tuota hakemistoa?

hunajavohveli [29.12.2003 13:48:37]

#

Yritin kerran tehä tällaista itsekin. (tai siis ainakin sellaista, joka pystyy lukemaan BMP-tiedostoa), mutta siinä näkyi vain jotain merkkejä, joista ei tajunnut mitään. Olisi tietysti pitänyt lukea kuva Binaari-muodossa.

mamaze [01.03.2004 21:22:29]

#

joo, tämä ei toimi mulla ainakaa alkuunkaan. Se valittaa jotai End-of-statement (tiedän kyllä mitä se tarkoittaa), mutta ei tuollaisia pitäisi olla tässä vinkissä. Varmasti kuitenkin Antti on saanut sen toimimaan. En epäile etteikö tuo toimisi, mutta aika monella se ei toimi. minullakaan. No, kaippa sen saa vielä toimimaan...:)

juoppo [17.04.2004 17:17:29]

#

Tuo pitäs saaha subbiin. Vaan ei toimi.

herkko [31.05.2004 21:48:07]

#

Hmm.. Tätä voisin jopa käyttää erään pelini alussa (mikäli vaan saan opeteltua kirjastojen käytön kunnolla..) :). Saat nimesi kiitoksiin!

CMouse [06.06.2004 13:12:11]

#

saiskohan tätä käyttää omassa pelissä?
meinaan tota vois jopa hyödyntää

E.K.Virtanen [01.11.2004 15:47:30]

#

hmm...pää raksuttaa taas tyhjyyttään. Miten saan tuon koodin lukemaan 100*100 alueen vaikkapa 640*400 kuvasta?

Juhko [07.10.2006 18:31:19]

#

Kiva, mutta tuo "tuntematon kuvatyyppi" ärsyttää.

Codeprofile [08.12.2006 22:51:30]

#

Tuotahan voisi hyödyntää monien QB-sovellusten alussa.

Dude [07.08.2007 12:07:58]

#

kala kirjoitti:

No eipä tollasella kyllä mitään tee jos ei edes RLE-kuvia osaa purkaa. Se RLE pakattu BMP on kyllä yleinen.

mä en oo eres kuullu tätä ennen rle kuvista. tuo olis ollu kätevämpi SUBissa ku sais vaan liittää omaa koodiin.
Edit: Huono että muuttaa palettia.

Edit2:kala: no tee sellaanen.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta