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); }
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.
Koko Windowsko jumiutuu, ei vain ohjelmasi ikkuna? Eikö mSpecialColorEffect()iä voisi laittaa omaan säikeeseensä?
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.
Kiitos neuvoista =)
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.
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.
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.
Tuota en tullut ajatelleeksi... kaiketi väliaikaisen bitmap.kuvan saa c++.lla tehtyä...
annatko vielä vinkin ;)
toimiihan c++:lla BitBlt yms apit
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.
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
Aihe on jo aika vanha, joten et voi enää vastata siihen.