Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB6: [vb6] GetDiBitsin käyttö tietyn pikselin etsimiseen värin perusteella

Sivun loppuun

JussiR [04.02.2009 17:41:35]

#

Hei,

Olen tähän asti käyttänyt GetPixeliä siihen että etsin pikselin tietystä ikkunasta, joka vastaa määriteltyä väriä. Mutta nykyisiin tarkoituksiin se on liian hidas.

Tässä esimerkki miten käytin GetPixeliä siihen, että siirsinn kursorin löydetyn pikselin x,y kohtaan:

Public Function CursorToColor(windowHWND As Long, colorcode As Long)
Dim wndRect As RECT
Dim X As Long, Y As Long, test As Long

GetWindowRect windowHWND, wndRect
test = GetDC(windowHWND)
For Y = 0 To (wndRect.Bottom - wndRect.Top)
    For X = 0 To (wndRect.Right - wndRect.Left)
        If GetPixel(test, X, Y) = colorcode Then
        SetCursorPos X + wndRect.Left, Y + wndRect.Top
        ReleaseDC test, windowHWND
        Exit Function
        End If
    Next X
Next Y
ReleaseDC test, windowHWND
End Function

Miten GetDiBitsiä voisi käyttää samalla tavalla kui käytän tuossa esimerkissä GetPixeliä? Yritin selvittää Googlella mutta en ymmärtänyt GetDiBitsistä yhtään mitään..

Tässä esimerkki missä käytettään GetDiBitsiä jonkin kuvan tarkasteluun tjs.
http://www.codeguru.com/vb/gen/vb_graphics/gdi/article.php/c2381

Merri [04.02.2009 18:11:39]

#

Jos vaikka GetBitmapBits olisi helpompi:

Option Explicit

Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long

Private Type RGBA
    Red As Byte
    Green As Byte
    Blue As Byte
    Alpha As Byte
End Type

Private Sub Form_Load()
    Dim Tavut() As RGBA, Leveys As Long, Korkeus As Long
    If Picture Is Nothing Then
        MsgBox "Aseta kuva formiin!"
    Else
        ' laske leveys & korkeus
        Leveys = ScaleX(Picture.Width, vbHimetric, vbPixels)
        Korkeus = ScaleY(Picture.Height, vbHimetric, vbPixels)
        ' alusta tavut
        ReDim Tavut(Leveys * Korkeus - 1)
        ' hae kaikki värit
        GetBitmapBits Picture.Handle, Leveys * Korkeus * 4, Tavut(0)
        ' tulosta ensimmäisen pikselin tiedot
        Debug.Print Tavut(0).Red, Tavut(0).Green, Tavut(0).Blue
    End If
End Sub

En jaksa tähän hätään alkaa muistella, mikä on järkevin tapa hakea kuvan handle tunnetusta DC:stä, joten sen osan saat selvittää muualta tai odottaa jonkun toisen apua.

Sitten eräs muu asia joka voi kiinnostaa:

X = Indeksi Mod Leveys
Y = Indeksi \ Leveys

Tämä lähinnä siksi, että moniulotteiset taulukot ovat hitaampia kuin yksiulotteinen. Lisäksi pitää pysytellä nollapohjaisuudessa, jotta tuota laskukaavaa ei tarvitse monimutkaistaa.

JussiR [04.02.2009 18:30:00]

#

Täytyy testata onko tuokin väh. 3 kertaa nopeampi kuin GetPixel.

EDIT: Miten saisin tietoon noiden pikselien yhteismäärän että tiedän kuinka pitkälle pitää tarkistaa pikselit for loopissa?

Testaan tuota nyt punaisella kuvalla mutta jostain kumman syystä R:n arvo ei ole koko ajan 255 vaan sen sijaan G: tai B:n arvo :S

JussiR [05.02.2009 19:38:53]

#

Sain nyt toimimaan GetDiBitsin niin että se etsii tietyn värin ikkunasta ja laittaa kursorin siihen kohtaan. Mutta millä laskukaavalla voin laskea mistä kohdasta värin tarkistus pitää aloittaa jos haluan aloittaa sen esim kohdasta 100,100?
Koko alueen pikseleiden määrän laskin width*height.

Ne pikselit menee siis näin.
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18

Esim kohta 10:n X on 1 ja Y on 2.

Eli miten lasken esim monesko 4,2 on? Se on 13.
Taitaa olla aika helppo juttu.. mutta silti kysyn :D

Grez [05.02.2009 21:14:41]

#

Yleisesti ottaen y * width + x (kun kaikki alkaa 0:sta)

Jos aloitat x:n ja y:n laskemisen 1:stä, mutta taulukko alkaa nollasta, niin:
(y - 1) * width + x - 1

Jos taulukkokin alkaa 1:stä kuten esimerkissäsi (harvemmin kuitenkaan alkaa oikeasti) niin
(y - 1) * width + x

JussiR [06.02.2009 15:56:06]

#

Kiitoksia sain toimimaan etsimisen aloituskohdan, mutta pitääkö koko juttu koodata uudestaan jos haluan että se etsii esim alueelta 100,100-300,300, ilman että käy X akselia läpi 300:sta eteenpäin turhaan?

For Offset = startIndex To MaxOffset
    If ScreenBits(Offset) = color Then
        Dim x As Long, y As Long
        x = Offset Mod wndWidth
        y = Offset / wndWidth
        info.Caption = "Color " & color & " found at " & x & ", " & y
        Exit For
    End If
Next Offset
MaxOffset = wndWidth * wndHeight
startIndex = (Ystart - 1) * wndWidth + Xstart - 1

Merri [06.02.2009 16:14:57]

#

Voit esimerkiksi käyttää for loopin askellusta hyväksi:

For OffsetY = startIndex To MaxOffset Step wndWidth
    For Offset = OffsetY To OffsetY + 200

    Next Offset
Next OffsetY

JussiR [06.02.2009 18:29:51]

#

Jostain syystä ei tänään riittänyt älykkyys tuon tajuamiseen vaikka näyttää aika helpolta^ :S

Mutta tässä on esimerkki ohjelman koodi niille, jotka sen haluaa. Etsii valitusta ikkunasta määritellyn värin getdibitsillä.
http://www.jrantala.com/getdibits.zip

Metabolix [08.02.2009 20:18:36]

#

Voit tehdä silmukat koordinaattien kanssa ja laskea offsetin silmukan sisällä.

For y = 100 To 300
  OffsetY = y * wndWidth
  For x = 100 To 300
    Offset = OffsetY + x
    ' ...
  Next
Next

Merri [09.02.2009 17:54:18]

#

Toimintaselitys aiemmasta koodistani:

- startIndex = 100
- wndWidth = 300
- MaxOffset = 900

- For OffsetY = 100
- Onko OffsetY pienempi kuin MaxOffset (100 < 900)?
-- For Offset = OffsetY (Offset = 100)
-- Offset looppaa kunnes Offset > OffsetY + 200
-- Offset = 301, looppi päättyy

- For OffsetY = OffsetY + wndWidth (OffsetY = 400)
- Onko OffsetY pienempi kuin MaxOffset (400 < 900)?
-- For Offset = OffsetY (Offset = 400)
-- Offset looppaa kunnes Offset > OffsetY + 200
-- Offset = 601, looppi päättyy

- For OffsetY = OffsetY + wndWidth (OffsetY = 700)
- Onko OffsetY pienempi kuin MaxOffset (700 < 900)?
-- For Offset = OffsetY (Offset = 700)
-- Offset looppaa kunnes Offset > OffsetY + 200
-- Offset = 901, looppi päättyy

- For OffsetY = OffsetY + wndWidth (OffsetY = 1000)
- Onko OffsetY pienempi kuin MaxOffset (1000 < 900)?
- Loppu tuli: looppien päättymisen jälkeen OffsetY = 1000 ja Offset = 901

Sivun alkuun

Vastaus

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

Tietoa sivustosta