[C#] Image bewerken

Pagina: 1
Acties:
  • 104 views sinds 30-01-2008
  • Reageer

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Ik ben nu in C# bezig met een programma die van een foto een bepaalde kleur-range eruit kan filteren.
Ik heb het al wel werkend, maar het is gruwelijk traag.
Ik loop nu de hele image pixel voor pixel door (twee loops, 1 voor x en een voor y).
Ik heb dit ook ooit in Delphi gemaakt en daar kwam toen iemand met de opmerking om steeds de hele rij pixels in te lezen en dan te doorlopen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
for i := 0 to Bmp.Height - 1 do
begin
    Line := PByteArray(Bmp.ScanLine[i]);
    for j := 0 to Bmp.Width - 1 do
    begin
        k := j * 3;
        b1 := Line[k];
        g1 := Line[k+1];
        r1 := Line[k+2];
        (hier dan de kleuren eventueel wijzigen)
    end;
end;

Dit was echt heel veel sneller.
Maar hoe doe ik zoiets in C# ?
Ik kan er niks over vinden. :(

Bitmap.MakeTransparent() werkt overigens niet omdat die maar 1 kleur eruit filters en niet een kleur-range.

Of heeft iemand nog een betere manier om zoiets te doen ?
En hoe kan ik het beste kleuren vergelijken ?
De RGB-waarden steeds vergelijken werkt niet helemaal goed omdat in bepaalde gevallen R wel hoger is, maar G bijv. minder.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Niemand ??

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Kan je misschien je huidige trage code even neerzetten? Ik prog wel in C#, maar nog niets met plaatjes bewerken gedaan. Misschien dat ik wel wat kan zeggen als ik je code zie...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Nu doet ik het gewoon heel lomp: pixel voor pixel de image doorlopen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Bitmap image = new Bitmap(SourcePicture.Image);
for (int row=0; row < image.Height; row++)
{
    for (int col=0; col < image.Width; col++)
    {
        int r1, g1, b1, r2, g2, b2, r3, g3, b3;
        r1 = image.GetPixel(col, row).R;
        g1 = image.GetPixel(col, row).G;
        b1 = image.GetPixel(col, row).B;
        r2 = FilterColor1.BackColor.R;
        g2 = FilterColor1.BackColor.G;
        b2 = FilterColor1.BackColor.B;
        r3 = FilterColor2.BackColor.R;
        g3 = FilterColor2.BackColor.G;
        b3 = FilterColor2.BackColor.B;
        if (((r1 > r2) || (g1 > g2) || (b1 > b2)) & ((r1 < r3) || (g1 < g3) || (b1 < b3)))
        {
            image.SetPixel(col, row, System.Drawing.Color.Blue);
        }
    }
}
DestPicture.Image = image;

FilterColor1 en FilterColor2 zijn de kleuren die de range aangeven van de te vervangen kleuren.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

* ACM heeft geen C# kennis, maar wel java/c kennis
Dus als het niet klopt wat ik zeg... Gewoon negeren ;)

Haal dit:
"int r1, g1, b1, r2, g2, b2, r3, g3, b3;"
Uit je binnenste for-loop en zet het boven je buitenste for-loop. Die waarden overschrijf je toch elke keer dus dat maakt niet uit. Maar dan krijg je niet onnodige geheugen allocaties.

Levert
code:
1
2
3
4
5
6
r2 = FilterColor1.BackColor.R;
g2 = FilterColor1.BackColor.G;
b2 = FilterColor1.BackColor.B;
r3 = FilterColor2.BackColor.R;
g3 = FilterColor2.BackColor.G;
b3 = FilterColor2.BackColor.B;

Altijd dezelfde waarden op? Ik vermoed van wel...
Zoja, ook buiten je buitenste for-loop plaatsen.

Daarnaast doe je 3x getPixel, als je die ene pixel es "cached", dus buiten je buitenste forloop een 'Pixel hulp;' oid declareren en dan daarbinnen 'hulp = getPixel(row, col)' whatever.

En vervolgens r1 = hulp.R; b1=hulp.B etc.

Het enige wat je dan nog kan optimaliseren is die if die je hebt.
Als je dingen zo kan groeperen dat ze sneller als false worden gezien (bijvoorbeeld die ||'s en &&'s anders opzetten?) zal ook dat sneller zijn.

Moet je trouwens niet ipv '&' '&&' neerzetten?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 09 december 2001 11:55 schreef ACM het volgende:

Haal dit:
"int r1, g1, b1, r2, g2, b2, r3, g3, b3;"
Uit je binnenste for-loop en zet het boven je buitenste for-loop. Die waarden overschrijf je toch elke keer dus dat maakt niet uit. Maar dan krijg je niet onnodige geheugen allocaties.
offtopic:
Zorgt bij java de java compiler daar niet voor? (ik weet het dus niet) :)

  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

Alarmnummer: dat ints buiten de for loop komen?

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 09 december 2001 12:03 schreef limoentje het volgende:
Alarmnummer: dat ints buiten de for loop komen?
Ja.. en bijvoorbeeld het volgende:
code:
1
2
3
4
5
6
7
8
for(int k=0;k<10;k++)
{
...
}

for(int k=0;k<20;k++)
{
}

hierin wordt 2 keer de variable k in een forlus aangemaakt, maar je kan deze natuurlijk hergebruiken. Ik weet dus niets af van deze soort compiler optimalisaties, dus alle info is welkom.

  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

Volgens mij doet Java dat niet, variabelen die niet veranderen buiten de for loop plaatsen. Waarom niet? Omdat je in Java te maken hebt met de scope van variabelen. Als een var binnen de for loop gedeclareerd wordt issie alleen in die loop te gebruiken volgens mij. In principe zou je dan nog wel op compiler niveau uit kunnen zoeken of het niet handiger is om bepaalde "constanten" buiten de for loop te plaatsen, maar ik verwacht dat dat in Java niet gedaan wordt.

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

ik bedoel ook op compiler niveau.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zondag 09 december 2001 11:58 schreef Alarmnummer het volgende:
offtopic:
Zorgt bij java de java compiler daar niet voor? (ik weet het dus niet) :)
En?
Daar moet je natuurlijk niet blindelings op vertrouwen. Als je zelf ziet dat dat beter kan moet je het direct doen...

Denken ala "oh, dat doet de compiler wel" is natuurlijk niet handig (er zijn altijd dingen die jij wel weet maar de compiler niet, waardoor dan ineens de compiler het niet doet en de boel instort kwa performance)

  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

ACM: jawel! right on! handmatige optimalisatie is leeerrrrzaam en handig!

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Yep.. maar je krijgt meestal viezere code dan als je het niet doet. (Ik optimaliseer zelf ook op plaatsen waar het nodig is) maar ik wil weten wat de compiler voor je doet.

De echte performance winst zit hem meestal in de macro optimalisatie (dus algortime keuze, object opbouw ed) en niet in dit soort dingen. (alhoewel een putpixel die traag is verziekt ook het hele systeem). Ik ben eerlijk gezegd van mening dat een groot deel van de micro optimalisaties door de compiler opgelost moeten worden doordat de onderhoudbaarheid van de code gevaar loopt.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zondag 09 december 2001 12:28 schreef Alarmnummer het volgende:
Yep.. maar je krijgt meestal viezere code dan als je het niet doet. (Ik optimaliseer zelf ook op plaatsen waar het nodig is) maar ik wil weten wat de compiler voor je doet.
Tsja, soms krijg je dan vieze code ;)

Maar optimalisaties zoals ik hierboven beschreef vind ik niks viezer en maakt het nog es een stuk duidelijker, dat die waarden bijvoorbeeld niet veranderen.

Overigens was ik nog iets vergeten te vragen :)
Als je een filter als:
R(50,60)
B(50,60)
G(50,60)

Hebt, neem ik aan dat een kleur als (100,0,0) niet vervangen mag worden?
Dat gebeurd nu wel ;)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 09 december 2001 12:34 schreef ACM het volgende:

[..]

Tsja, soms krijg je dan vieze code ;)

Maar optimalisaties zoals ik hierboven beschreef vind ik niks viezer en maakt het nog es een stuk duidelijker, dat die waarden bijvoorbeeld niet veranderen.
Ik ben het met je eens dat dingen die niet veranderen buiten de for lus kunnen staan. Alhoewel die waarde in die lus alleen gebruikt worden, dus hun noodzakelijke scope is dan ook binnen die lus en niet erbuiten. Dus het zou programma technisch wel correcter zijn om ze er wel in te plaatsen en niet erbuiten. (Het word daardoor wel onnodig traag).

  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

Op zondag 09 december 2001 12:37 schreef Alarmnummer het volgende:
Ik ben het met je eens dat dingen die niet veranderen buiten de for lus kunnen staan. Alhoewel die waarde in die lus alleen gebruikt worden, dus hun noodzakelijke scope is dan ook binnen die lus en niet erbuiten. Dus het zou programma technisch wel correcter zijn om ze er wel in te plaatsen en niet erbuiten.
Ik ken de Java garbage-collection niet goed maar is het niet zo dat die automatisch de variabelen waarvan de scope alleen maar de lus is, opruimt zodra de lus afgelopen is?
Dan zou het dus totaal niet slim zijn om ze buiten de lus te plaatsen! Levert snelheid op maar ook onnodige geheugenallocatie (hoewel niet veel voor een paar integers).

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zondag 09 december 2001 12:37 schreef Alarmnummer het volgende:
Alhoewel die waarde in die lus alleen gebruikt worden, dus hun noodzakelijke scope is dan ook binnen die lus en niet erbuiten.
In dit geval wil je dat die waarden "overal" in de lus beschikbaar zijn, dus ligt de scope er imho "omheen" of "bovenop" maar hoef je ze dus niet perse binnen te zetten.

Bovendien zijn het nog steeds variabelen waarvan de waarde maar 1 keer opgevraagd hoeft te worden dus zou je gewoon dom bezig zijn als je ze in een for-lus gooit.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op zondag 09 december 2001 11:55 schreef ACM het volgende:
* ACM heeft geen C# kennis, maar wel java/c kennis
Dus als het niet klopt wat ik zeg... Gewoon negeren ;)

Haal dit:
"int r1, g1, b1, r2, g2, b2, r3, g3, b3;"
Uit je binnenste for-loop en zet het boven je buitenste for-loop. Die waarden overschrijf je toch elke keer dus dat maakt niet uit. Maar dan krijg je niet onnodige geheugen allocaties.

Levert
code:
1
2
3
4
5
6
r2 = FilterColor1.BackColor.R;
g2 = FilterColor1.BackColor.G;
b2 = FilterColor1.BackColor.B;
r3 = FilterColor2.BackColor.R;
g3 = FilterColor2.BackColor.G;
b3 = FilterColor2.BackColor.B;

Altijd dezelfde waarden op? Ik vermoed van wel...
Zoja, ook buiten je buitenste for-loop plaatsen.

Daarnaast doe je 3x getPixel, als je die ene pixel es "cached", dus buiten je buitenste forloop een 'Pixel hulp;' oid declareren en dan daarbinnen 'hulp = getPixel(row, col)' whatever.

En vervolgens r1 = hulp.R; b1=hulp.B etc.

Het enige wat je dan nog kan optimaliseren is die if die je hebt.
Als je dingen zo kan groeperen dat ze sneller als false worden gezien (bijvoorbeeld die ||'s en &&'s anders opzetten?) zal ook dat sneller zijn.

Moet je trouwens niet ipv '&' '&&' neerzetten?
Bedankt voor de tips.
Maar deze wijzigingen maken slechts een klein verschil (ik zal ze wel doorvoeren hoor).
Maar mij gaat het meer om het feit dat ik nu pixel voor pixel het plaatje doorloop.
In Delphi kon ik van een rij pixels een PByteArray maken en die doorlopen (dmv scanline).
En toen was ie echt tig keer sneller.
Dus zoiets zoek ik ook in C#.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zondag 09 december 2001 13:57 schreef maikel het volgende:
In Delphi kon ik van een rij pixels een PByteArray maken en die doorlopen (dmv scanline).
En toen was ie echt tig keer sneller.
Dus zoiets zoek ik ook in C#.
In principe is een image een array van bytes, dus wel een beetje gek dat het dan ineens sneller zou moeten gaan.

Maar verder kan ik je zo specifiek niet helpen :)
Is het nu dus zo dat een app in delphi die hetzelfde doet vele malen sneller is dan je C# app ?

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op zondag 09 december 2001 12:34 schreef ACM het volgende:

[..]

Tsja, soms krijg je dan vieze code ;)

Maar optimalisaties zoals ik hierboven beschreef vind ik niks viezer en maakt het nog es een stuk duidelijker, dat die waarden bijvoorbeeld niet veranderen.

Overigens was ik nog iets vergeten te vragen :)
Als je een filter als:
R(50,60)
B(50,60)
G(50,60)

Hebt, neem ik aan dat een kleur als (100,0,0) niet vervangen mag worden?
Dat gebeurd nu wel ;)
Bedoel je hier dat if-statement mee waarin ik alle kleuren vergelijk ?
Dit kan nog wel anders ja, maar is niet het grootste probleem op dit moment.
En hoe kan ik dat het beste doen ?
Welke kleuren zitten er bijv. tussen lichtblauw en blauw ?
Gaat dat altijd goed als ik dan gewoon de RGB-waarden afzonderlijk vergelijk ?

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zondag 09 december 2001 14:00 schreef maikel het volgende:
Bedoel je hier dat if-statement mee waarin ik alle kleuren vergelijk ?
Dit kan nog wel anders ja, maar is niet het grootste probleem op dit moment.
En hoe kan ik dat het beste doen ?
Welke kleuren zitten er bijv. tussen lichtblauw en blauw ?
Gaat dat altijd goed als ik dan gewoon de RGB-waarden afzonderlijk vergelijk ?
Ik zou eigenlijk niet weten hoe je dat beter kan doen :)
Misschien alleen naar de meest significante kleur (R, G of B) kijken, maar ook dat is erg lastig te doen.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op zondag 09 december 2001 14:00 schreef ACM het volgende:

[..]

In principe is een image een array van bytes, dus wel een beetje gek dat het dan ineens sneller zou moeten gaan.

Maar verder kan ik je zo specifiek niet helpen :)
Is het nu dus zo dat een app in delphi die hetzelfde doet vele malen sneller is dan je C# app ?
Op dit moment wel. Maar toen ik in Delphi ook het plaatje doorliep dmv twee for-loops was het ook heel erg traag.
Dit heeft volgens mij te maken met het steeds aanspreken van het plaatje.
Als je een rij pixels in een ByteArray zet hoef je de image niet meer te gebruiken en dus is het sneller. Denk ik.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zondag 09 december 2001 14:03 schreef maikel het volgende:
Als je een rij pixels in een ByteArray zet hoef je de image niet meer te gebruiken en dus is het sneller. Denk ik.
Het zou idd kunnen dat de accesses een stuk sneller zijn dan.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op zondag 09 december 2001 14:10 schreef ACM het volgende:

[..]

Het zou idd kunnen dat de accesses een stuk sneller zijn dan.
Ja, het scheelt echt gigantisch veel.
Nu moet ik een paar seconden wachten voordat ie klaar is.
En bij de Delphi-versie gebeurt het real-time. Ik kan gewoon de kleuren-range aanpassen en zie het meteen in het plaatje veranderen.
Maar hoe moet dit nu in C# ?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
limoentje: Ik ken de Java garbage-collection niet goed maar is het niet zo dat die automatisch de variabelen waarvan de scope alleen maar de lus is, opruimt zodra de lus afgelopen is?
Dan zou het dus totaal niet slim zijn om ze buiten de lus te plaatsen! Levert snelheid op maar ook onnodige geheugenallocatie (hoewel niet veel voor een paar integers).
In Java worden integers niet op de heap-gealloceerd (zoals in vrijwel alle talen dus) maar op de stack. Hierdoor komt er helemaal geen garbage-collection aan te pas. Per functie is er een frame op de stack voor lokale variabelen en andere temps. Er zal voor deze integers ruimte in dit frame worden gereserveerd (de frame-size is volgens mij constant voor een functie in Java). Het maakt dus qua geheugen-gebruik in principe niet uit of ze in de for-loop of erna worden gedeclareerd.
ACM: Denken ala "oh, dat doet de compiler wel" is natuurlijk niet handig (er zijn altijd dingen die jij wel weet maar de compiler niet, waardoor dan ineens de compiler het niet doet en de boel instort kwa performance)
Eigenlijk zou het gedrag van een compiler ook gedocumenteerd moeten zijn. Dit uitermate symplistische omhoog-liften van de declaraties zou elke compiler moeten kunnen. In principe veroorzaakt de declaratie zelf nog geeneens het probleem: hiervoor is helemaal geen code nodig. Wat wel een probleem is, is de standaard assignment naar 0. Deze zal in elke loop worden gedaan. Deze kan in principe door een compiler ook worden weg-geoptimaliseerd omdat de variabelen gelijk een assignment om hun kiezen krijgen, maar dat vereist al iets meer werk.

Overigens ben ik het absoluut niet eens met de statemet dat jij meer weet dan de compiler ;) . De compiler weet op veel punten meer dan jij ;) . Via liveness analyses kunnen er bijvoorbeeld variabelen verwijderd worden omdat ze in hetzelfde register kunnen (ze worden dan niet allebei tegelijk gebruikt in de code). Ook kunnen loop-optimalisaties worden toegepaste en kunnen invarianten uit loops worden getrokken. Als je echt een goede optimaliserende compiler neemt ben je kansloos als programmeer om het in details beter te doen. Het globale algoritme is natuurlijk wel een hele belangrijke kwestie :) .
Alarmnummer: Zorgt bij java de java compiler daar niet voor? (ik weet het dus niet) .
In principe doet de Java compiler zelf heel erg weinig met dit soort stuff. Ik vermoed echter dat de Hotspot just in time compiler hier wel mee aan de slag gaat.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Op zondag 09 december 2001 12:05 schreef Alarmnummer het volgende:

[..]

Ja.. en bijvoorbeeld het volgende:
code:
1
2
3
4
5
6
7
8
for(int k=0;k<10;k++)
{
...
}

for(int k=0;k<20;k++)
{
}

hierin wordt 2 keer de variable k in een forlus aangemaakt, maar je kan deze natuurlijk hergebruiken. Ik weet dus niets af van deze soort compiler optimalisaties, dus alle info is welkom.
Deze code werkt zo niet, omdat de scope van k na de for-lus niet afgelopen is.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Zouden we weer een beetje on-topic kunnen gaan ?
We dwalen nu best wel af.

Verwijderd

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static protected unsafe void ChangeColor( Bitmap bitmap, Color old, Color Replace ) 
{
    Rectangle rcBitmap = new Rectangle( 0, 0, bitmap.Width, bitmap.Height );
    BitmapData bitmapdata = bitmap.LockBits( rcBitmap,ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb );

    uint oldC,repC;
    uint *pUIntData = (uint *) bitmapdata.Scan0.ToPointer();
    int    iDataLength = bitmapdata.Height * (bitmapdata.Stride >> 2 );

    oldC = (uint)((old.R << 16) + (old.G << 8) + (old.B));
    repC = (uint)((0xff000000) + (Replace.R << 16) + (Replace.G << 8) +(Replace.B));
    
    for( int index = 0; index < iDataLength; index ++ ) 
    {
        if ((pUIntData[index] & 0x00ffffff) == oldC)
            pUIntData[index]=repC;
    }
    bitmap.UnlockBits( bitmapdata );
}

Unsafe code saves the day :Y)

(Gebasseerd op een voorbeeltje van de dotnet mailing list)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Wat is je code nu dan? De tips van ACM leken mij al erg goed.... Vooral het voorkomen van herhaling van methode aanroepen zou weleens aardig wat op kunnen leveren (1x GetPixel, constanten omhoog werken en dergelijke).

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op zondag 09 december 2001 15:18 schreef mbravenboer het volgende:
Wat is je code nu dan? De tips van ACM leken mij al erg goed.... Vooral het voorkomen van herhaling van methode aanroepen zou weleens aardig wat op kunnen leveren (1x GetPixel, constanten omhoog werken en dergelijke).
M'n code is nu hetzelfde als eerst, maar dan met de aanpassingen van ACM.
Maar dat zijn echt details, het gaat mij echt om de manier waarop ik de hele image doorloop.
Volgens mij heeft Yarvieh wel gelijk, alleen heb ik een hekel aan pointers en zo. :)

Verwijderd

Op zondag 09 december 2001 16:32 schreef maikel het volgende:
het gaat mij echt om de manier waarop ik de hele image doorloop.
[...]
alleen heb ik een hekel aan pointers en zo.
Je hebt 2 keuzes, met een pointertje er door heen lopen of met GetPixel maar je schijnt ze geen van 2'en te willen gebruiken, wat wil je dan?! :?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het ging niet alleen om het omhoog zetten van de declaraties, maar ook om het uitfilteren van enkele aanroepen.

Je krijgt dan uiteindelijk dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Bitmap image = new Bitmap(SourcePicture.Image);

int r1;
int g1;
int b1;
int r2 = FilterColor1.BackColor.R;
int g2 = FilterColor1.BackColor.G;
int b2 = FilterColor1.BackColor.B;
int r3 = FilterColor2.BackColor.R;
int g3 = FilterColor2.BackColor.G;
int b3 = FilterColor2.BackColor.B;

? pixel;

int height = image.Height;
int width = image.Width;

for (int row=0; row < height; row++)
{

    for (int col=0; col < width; col++)
    {
        pixel = image.GetPixel(col, row);

        r1 = pixel.R;
        g1 = pixel.G;
        b1 = pixel.B;

        if (((r1 > r2) || (g1 > g2) || (b1 > b2)) & ((r1 < r3) || (g1 < g3) || (b1 < b3)))
        {
            image.SetPixel(col, row, System.Drawing.Color.Blue);
        }
    }
}
DestPicture.Image = image;

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op Sunday 09 December 2001 14:33 schreef mbravenboer het volgende:
Overigens ben ik het absoluut niet eens met de statemet dat jij meer weet dan de compiler ;) . De compiler weet op veel punten meer dan jij ;) .
Tuurlijk, maar jij weet wat de code doet (of denkt te weten wat het hoort te doen, maar dan zitten er vaak bugs in :P (en die kunnen dan natuurlijk ook niet in je code maar in je denkpatroon zitten) ).
De compiler niet. Jij weet dat een bepaalde functie altijd hetzelfde terug gaat geven in een bepaalde situatie, omdat jij die functie gemaakt hebt.

Dat zijn dingen die de compiler niet weet (of niet altijd kan weten).
En dat zijn de dingen waar ik op doelde.
Jij weet meer van je code (wat het doet, niet hoe het uiteindelijk gecompiled gaat worden en hoe het op die lage niveau's het best geassembleerd etc kan worden) in dat soort situaties.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op Sunday 09 December 2001 16:49 schreef Yarvieh het volgende:

[..]

Je hebt 2 keuzes, met een pointertje er door heen lopen of met GetPixel maar je schijnt ze geen van 2'en te willen gebruiken, wat wil je dan?! :?
Ik gebruik nu toch die unsafe code en dat werkt wel.
Maar ik heb nu:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Bitmap image = new Bitmap(SourcePicture.Image);
Rectangle rcBitmap = new Rectangle( 0, 0, image.Width, image.Height );
BitmapData bitmapdata = image.LockBits( rcBitmap,ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb );
uint *pUIntData = (uint *) bitmapdata.Scan0.ToPointer();
int iDataLength = bitmapdata.Height * (bitmapdata.Stride >> 2 );
while (!Terminated)
{
    for (int i=0; i < iDataLength; i++)
    {
        if (( (pUIntData[i] & 0x00ffffff) > C1) && ( (pUIntData[i] & 0x00ffffff) < C2))
            pUIntData[i] = (uint)((0xff000000) + (Color.Blue.R << 16) + (Color.Blue.G << 8) +(Color.Blue.B));
    }
    image.UnlockBits(bitmapdata);
    DestPicture.Image = image;
}

Ik gebruik die Terminated zodat ik de thread netjes kan laten eindigen. Anders blijft ie in de loop hangen.
Zo werkte dat in Delphi tenminste, maar daar zit het al in het Thread-object zelf. Hoe zit dit in C# ?
Alle voorbeelden die ik heb gezien gingen over een for-loop, dus geen oneindige loop. Die van mij moet oneindig doorgaan totdat ik 'm zelf stop.
C1 en C2 worden in m'n programma zelf ingesteld op de begin- en eindkleur van de kleurenrange.
Maar als ik het zo doe, krijg ik steeds een foutmelding:
Value null was found where an instance of an object was required.
Deze melding krijg ik bij de regel waarin de kleuren vergeleken worden.
Dit gaat de eerste keer nog goed, maar de keer daarna krijg ik dus die fout.
Het lijkt erop alsof ie de waarde kwijt is van pUIntData of zo.
Als ik die drie regels in m'n while-loop zet, werkt het wel goed. Maar omdat die waarden nooit veranderen lijkt me dit overbodig.

Verwijderd

Klopt je unlock 'm in je loop... dan is je pointer weer foetsie, volgende keer dat je loop weer begint, heb je ongeldige pointer, SJAKKA exception ;) Verder kan je waarschijnlijk buiten je loop eerst de waarde van blue in 'n uint proppen. Geen idee hoe goed de compiler het er uit optimized, maar als je 'm buiten je loop alsvast berekend, weet je zeker dat ie het niet voor iedere pixel opnieuw gaat doen.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op Sunday 09 December 2001 17:58 schreef Yarvieh het volgende:
Klopt je unlock 'm in je loop... dan is je pointer weer foetsie, volgende keer dat je loop weer begint, heb je ongeldige pointer, SJAKKA exception ;) Verder kan je waarschijnlijk buiten je loop eerst de waarde van blue in 'n uint proppen. Geen idee hoe goed de compiler het er uit optimized, maar als je 'm buiten je loop alsvast berekend, weet je zeker dat ie het niet voor iedere pixel opnieuw gaat doen.
Als ik die unlock er ook buiten zet krijg ik:
Bitmap region already locked.

Hij geeft dat aan bij de '}' van de Main-functie. :?

Verwijderd

Ik heb geen idee waar je die unlock nu gezet hebt dus kan je ook niet helpen.

Wat probeer je eigenlijk te bereiken, constant images bij werken in 'n thread?! lijkt me niet echt de meest optimale manier.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op Sunday 09 December 2001 18:09 schreef Yarvieh het volgende:
Ik heb geen idee waar je die unlock nu gezet hebt dus kan je ook niet helpen.

Wat probeer je eigenlijk te bereiken, constant images bij werken in 'n thread?! lijkt me niet echt de meest optimale manier.
Ik heb de unlock meteen na de '}' van de while-loop staan.
Maar hij gaf net dezelfde fout toen ik de unlock er helemaal uit had gehaald.

Ik wil inderdaad constant de kleur uit de foto filteren.
Nu is het nog onzin om dat constant te doen, maar als dit werkt wil ik het met een video-stream proberen. Vandaar dat het ook zo snel mogelijk moet gebeuren (met Delphi kwam ik al een heel eind).

Volgens mij weet ik al waar die fout door komt.
Ik probeer de 'image' toe te kennen aan 'DestPicture.Image' zonder dat ik eerst unlock heb gedaan.
Tenminste... toen ik die regel eruit haalde, deed ie het.
Maar als ik 'm unlock, moet ik 'm daarna toch weer locken zonder dat er iets verandert is.
Dit kost dus ook onnodig tijd. Is dit nog anders op te lossen ?

Verwijderd

Op Sunday 09 December 2001 18:12 schreef maikel het volgende:
maar als dit werkt wil ik het met een video-stream proberen.
Kan je daar niet beter DirectShow filter voor schrijven?

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op Sunday 09 December 2001 18:20 schreef Yarvieh het volgende:

[..]

Kan je daar niet beter DirectShow filter voor schrijven?
Daar heb ik ook wel aan gedacht ja.
Maar dat zie ik mezelf niet echt doen.
En hoe zit het met de DirectX-ondersteuning in .Net ??

Verwijderd

Op Sunday 09 December 2001 18:27 schreef maikel het volgende:
En hoe zit het met de DirectX-ondersteuning in .Net ??
Via de com interop, er zijn geruchten dat DX9 een native interface krijgt maar dat heb ik nog nergens bevestigd gezien.

  • maikel
  • Registratie: Januari 2001
  • Laatst online: 16:33
Op Sunday 09 December 2001 18:27 schreef Yarvieh het volgende:

[..]

Via de com interop, er zijn geruchten dat DX9 een native interface krijgt maar dat heb ik nog nergens bevestigd gezien.
Daar zijn zeker nog nergens tutorials over te vinden ?

Verwijderd

Op Sunday 09 December 2001 18:37 schreef maikel het volgende:
Daar zijn zeker nog nergens tutorials over te vinden ?
ja hoor zitten gewoon bij de framework sdk:

FrameWorkSDK\Samples\Technologies\Interop\Basic\DirectX

Verwijderd

Volgens mij heeft Yarvieh wel gelijk, alleen heb ik een hekel aan pointers en zo.
Dat komt dan slecht uit. Generieke C oplossing zonder classes e.d, 3 bytes per pixel (simpel aan te passen voor 8/15/16/32/whatever):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unsigned char* pBitmap = Blahblah;
int nWidth = Blah;
int nHeight = Blah;

for (unsigned char* pLine = pBitmap; pLine < pBitmap + nHeight * nWidth * 3; pLine += nWidth * 3) {
    for (unsigned char* pPixel = pLine; pPixel < pLine + nWidth * 3; pPixel += 3) {
        int nRed = pPixel[0];
        int nGreen = pPixel[1];
        int nBlue = pPixel[2];

        int nGrayValue = (nRed * 2) + (nGreen * 3) + nBlue;

        // Blahblahblah...

    }
}

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 09 december 2001 14:48 schreef OlafvdSpek het volgende:

[..]

Deze code werkt zo niet, omdat de scope van k na de for-lus niet afgelopen is.
Probeer het maar eens :) je zult zien dat de scope van k alleen in de for lus zit.
Pagina: 1