Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++-DLL:stä VB:n DoEvents-kutsu?

Sivun loppuun

JoreSoft [29.10.2008 15:20:20]

#

Olen tehnyt VB6 ohjelmaani DLL funktioita C++:lla, ja tärmännyt seuraavaan ongelmaan.

Kun C++ tekee kuvalle muutosta (kesto n. 10-20s) menee windows siksi aikaa aika lukkoon. vastaus olisi varmaan asettaa jonkinlainen DoEvents, silloin tällöin.

Mutta kuinka saan sen toteutettua? en löytänyt googlella mitään valaisevaa vastausta.

esimerkki:

void mSpecialColorEffect(short Index){
short x=0, y=0;int tCol=0;
t_RGB C, C1;


	do{
		do{
			C = ReadRGBValues( P1, x, y);
			switch (Index){
			case 0 ://0 = "Brown"
				C.R = abs(C.G * C.B) / 256;
				C.G = abs(C.B * C.R) / 256;
				C.B = abs(C.R * C.G) / 256;
				break;
			case 1 ://1 = "Liquid"
				C.R = ((C.G - C.B) * (C.G - C.B)) / 125;
				C.G = ((C.R - C.B) * (C.R - C.B)) / 125;
				C.B = ((C.R - C.G) * (C.R - C.G)) / 125;
			} // end switch
			PutC (x, y, RGB(C.R, C.G, C.B));
			x++;
		} while ( x <= Kuva.X - 1);
        y++;
        x = 0;
        /// TÄHÄN DoEvents ??    mutta miten?
	}while ( y <=Kuva.Y - 1);
}

Metabolix [29.10.2008 16:40:38]

#

Luultavasti tuosta tulee jotain niin rumaa, ettei siihen kannata ruveta. Helpommalla pääset, kun siirrät tuosta funktiosta ulomman silmukan VB:n puolelle ja lisäät y:n funktiolle parametriksi. Toinen vaihtoehto olisi tehdä tuosta oma säikeensä, mutta sekin vaatii taas astetta enemmän koodia.

ville-v [29.10.2008 16:48:04]

#

Koko Windowsko jumiutuu, ei vain ohjelmasi ikkuna? Eikö mSpecialColorEffect()iä voisi laittaa omaan säikeeseensä?

thefox [29.10.2008 17:59:58]

#

DoEventsin korvikkeena voit kokeilla käyttää Sleep-funktiota, esim Sleep(0) (tai suuempi arvo, ihan miten haluat). Sleep estää ohjelmaasi syömästä kaikkea prosessoriaikaa. Toinen vaihtoehto olisi asettaa säikeen prioriteetti normaalia alemmaksi.

JoreSoft [29.10.2008 18:30:26]

#

Kiitos neuvoista =)

Merri [29.10.2008 19:27:04]

#

Tuo on kyllä sen verran perustason matikkaa, ettei tuohon edes C:tä tarvittaisi ollenkaan. Itseasiassa C:llä kirjoittamisesta ei ole edes hyötyä, sillä heikko logiikka syö paljon nopeutta pois.

Olettaen että P1 on Long-taulukko, joka sisältää kuvatiedon:

Public Sub SpecialColorEffect(ByVal Index As Byte)
    Dim lngX As Long, lngY As Long, lngXY As Long
    Dim lngC As Long, lngR As Long, lngG As Long, lngB As Long

    ' ei tehdä jokaista pikseliä kohden tätä vertailua vaan vain kerran
    Select Case Index
        Case 0 ' Brown
            For lngY = 0 To Kuva.Y - 1
                For lngX = 0 To Kuva.X - 1
                    ' hae väri taulukosta
                    lngC = P1(lngXY + lngX)
                    ' erottele värit
                    'lngR = lngC And &HFF& (punaista ei käytetä)
                    lngG = (lngC And &HFF00&) \ &H100&
                    lngB = (lngC And &HFF0000) \ &H10000
                    ' laske uudet arvot
                    lngR = (lngG * lngB) \ &H100&
                    lngG = (lngB * lngR) \ &H100&
                    lngB = (lngR * lngG) \ &H100&
                    ' talleta uusi väri
                    P1(lngXY + lngX) = (lngR) Or (lngG * &H100&) Or (lngB * &H10000)
                Next lngX
                ' laske seuraavan rivin alku
                lngXY = lngXY + lngX
            Next lngY
        Case 1 ' Liquid
            For lngY = 0 To Kuva.Y - 1
                For lngX = 0 To Kuva.X - 1
                    ' hae väri taulukosta
                    lngC = P1(lngXY + lngX)
                    ' erottele värit; oletan että ReadRGBValues tekee tämän?
                    'lngR = lngC And &HFF& (punaista ei käytetä)
                    lngG = (lngC And &HFF00&) \ &H100&
                    lngB = (lngC And &HFF0000) \ &H10000
                    ' laske uudet arvot
                    lngR = ((lngG - lngB) * (lngG - lngB)) \ 125
                    lngG = ((lngR - lngB) * (lngR - lngB)) \ 125
                    lngB = ((lngR - lngG) * (lngR - lngG)) \ 125
                    ' talleta uusi väri
                    P1(lngXY + lngX) = (lngR) Or (lngG * &H100&) Or (lngB * &H10000)
                Next lngX
                ' laske seuraavan rivin alku
                lngXY = lngXY + lngX
            Next lngY
    End Select
End Sub

Sitten Advanced optimizations -kohdassa laittaa ruksi kohtiin "Remove Array Bounds check" ja "Remove Integer Overflow Checks" niin vauhtia tulee roimasti lisää, kunhan ohjelman kääntää.

Voit tietty toteuttaa samat nopeusmuutokset myös C-koodillesi.

JoreSoft [30.10.2008 10:05:39]

#

P1 on kuvan HDC - kahva ja C on tyyppiä t_RGB, joka on

	struct t_RGB{
		int R,G,B;
	};

C = ReadRGBValues( P1, x, y); Luetaan yksi pikseli ja muutetaan se RGB arvoiksi.

koko koodi on niin iso, ettei jokaiseen switch kohtaan kehdannut laittaa omaa silmukkakiertoa, vaan tarkoitus oli juuri sijoittaa kaikki noi efektit samaan. switch ei kaiketi hirveästi toimintaa hidasta?

void mSpecialColorEffect(short Index){
short x=0, y=0;int tCol=0;
t_RGB C, C1;


	do{
		do{
			C = RdRGBValues( P1, x, y);
			C1 = RdRGBValues(P1, x + 1, y + 1);
			switch (Index){
			case 0 ://0 = "Brown"
				C.R = abs(C.G * C.B) / 256;
				C.G = abs(C.B * C.R) / 256;
				C.B = abs(C.R * C.G) / 256;
				break;
			case 1 ://1 = "Liquid"
				C.R = ((C.G - C.B) * (C.G - C.B)) / 125;
				C.G = ((C.R - C.B) * (C.R - C.B)) / 125;
				C.B = ((C.R - C.G) * (C.R - C.G)) / 125;
				break;
			case 2 ://2 = "Yellow"
				C.B = ((C.G - C.R) * (C.G - C.R)) / 125;
				C.R = ((C.G - C.B) * (C.G - C.B)) / 125;
				C.G = ((C.B + C.R) * (C.B + C.R)) / 125;
				break;
			case 4 ://4 = "Dark moon"
				C.R = abs(C.R - 64);
				C.G = abs(C.R - 64);
				C.B = abs(C.R - 64);
				break;
			case 5 ://5 = "Total eclipse"
				C.R = abs(C.G - 64);
				C.G = abs(C.G - 64);
				C.B = abs(C.G - 64);
				break;
			case 6 ://6 = "Purple rain"
				C.R = (int)abs((C.G + C.R) / 2.0);
				C.G = (int)abs((C.B + C.G) / 2.0);
				C.B = (int)abs((C.R + C.B) / 2.0);
				break;
			case 7 ://7 = "Spooky"
				C.G = abs(C.R + C.G / 2);
				C.B = abs(C.R + C.B / 2);
				break;
			/*case 8 ://8 = "Unreal"
				if ((C.G == 0) || (C.B == 0)){
					C.G = 1;
					C.B = 1;
				}
				C.R = abs(sin(atan(C.G / C.B)) * 125 + 20);
				C.G = abs(sin(atan(C.R / C.B)) * 125 + 20);
				C.B = abs(sin(atan(C.R / C.G)) * 125 + 20);
				break; */
			case 9 ://9 = "Flame"
				tCol =INT((C.R + C.G + C.B) /(float)3.0);
				if (C.R > C.B){
					C.R = abs(C.R + tCol);
					C.B = abs(C.B - tCol);
				}
				break;
			case 10 ://10 = "Aquarel"
				if (C.R < 128 && C.G < 128 && C.B < 128){
					C.R = 2 * C.R; C.G = 2 * C.G; C.B = 2 * C.B;
				}else{
					C.R = C.R / 2; C.G = C.G / 2; C.B = C.B / 2;
				}
				break;
			case 11 :// Freeze
				C.R = (int)(abs((C.R - C.G - C.B) * 1.5));
				C.G = (int)(abs((C.G - C.B - C.R) * 1.5));
				C.B = (int)(abs((C.B - C.R - C.G) * 1.5));
				break;
	        //Tämä ei kuulu Special efekti valikkoon
			case 30 :// GaryScale
				//first make the red component
				C.R = (int)(C.R * 0.3 + C.G * 0.59 + C.B * 0.11);
				//then equal green and blue to red
				C.G = C.R;
				C.B = C.R;
			} // end switch
			// Tarkistetaan ylivuodeot
			if (C.R > 255) C.R = 255; else if (C.R < 0 ) C.R = 0;
			if (C.G > 255) C.G = 255; else if (C.G < 0 ) C.G = 0;
			if (C.B > 255) C.B = 255; else if (C.B < 0 ) C.B = 0;
			PutC (x, y, RGB(C.R, C.G, C.B));  // Tallettaa pikselin
			x++;
		} while ( x <= Kuva.X - 1);
        y++;
        x = 0;
	}while ( y <=Kuva.Y - 1);
}

Toivottavasti noista efekteistä olisi jollekkin hyötyä. eihän ne ole optimoituja, kuten merrillä (ja kiitos merri) mutta kuitenkin.

Merri [30.10.2008 19:50:50]

#

Käytät GetPixeliä ja SetPixeliä? Ei pahemmin selviä tuosta koodistasi, kun en tunne noita PutC yms. funkkareita. Ainakin olisi paljon parempi hakea kuvadata kokonaisuudessaan, muokata sitä ja sitten tallettaa kaikki kerralla takaisin. Välistä katoaa suuri määrä ylimääräistä prosessointia.

JoreSoft [31.10.2008 19:02:35]

#

Tuota en tullut ajatelleeksi... kaiketi väliaikaisen bitmap.kuvan saa c++.lla tehtyä...
annatko vielä vinkin ;)
toimiihan c++:lla BitBlt yms apit

Merri [31.10.2008 20:53:20]

#

En ole paljoa käytellyt noita API-kutsuja pahemmin itsekään, joten mulkkasin vaan nopeasti yhden esimerkin, joka ottaa VB:n formin kuvan ja käsittelee sen tuolla aiemmin kirjoittamallani aiemmin testaamattomalla funktiolla. Käytössä kutsut GetObject, GetBitmapBits ja SetBitmapBits. Lisäksi olisi hyvä olla kuvan BITMAP-rakennetiedot, jotta tarvittava bufferi voitaisiin varata.

Tuo formin kuva on minulla kooltaan automaattisesti hulppeat 6720 x 1080 pikseliä, joka tavuiksi muutettuna tekee melkein 27 Mt. Tästä huolimatta käännetty VB-koodi rullaa kuvan kaikki tavut lävitse niin nopeasti etten pahemmin huomaa eroa normaaliin käynnistykseen. IDE:n alla onkin sitten hidastelua jo enemmän.

Laitoin sorsan näkyviin http://kontu.selfip.info/vb6/putka/bitmapbits/ - siellä on myös esimerkki.exe kaikille kiinnostuneille (muistakaa tarkistaa viruksien ym. varalta, netissä pitää olla varovainen)


Selvittämällä hBitmap-arvon voit minkä tahansa kuvan syöttää GetBitmapBitsille ja saat sitten valmiiksi luomaasi bufferiin tarvitut tavut.

JoreSoft [01.11.2008 08:31:19]

#

Tarkoitin lähinnä, kuinka luoda C++ koodissa ensin väliaikainen bitmap, johon siirretään esim BitBlt komennolla VB:ssä oleva kuva.
Prosessin jälkeen kuva siirretään takaisin VB:ssä olevaan kuvaan. BitBlt taas =)

Enköhän löydä jotain koodia, kun etsin.

ps. noita kuvankäsittely aliohjelmia on kymmeniä...
Pitäisikö siis luoda globaali bitmap, jota päivitetään aina kun VB:ssä editoitava kuva muuttuu?

Tuo sun tekemä koodi toimii hyvin. ja nopeutta sai lisää, kun tein bitmapkontrollin, ja ScaleMode:ksi pixel


Sivun alkuun

Vastaus

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

Tietoa sivustosta