Toon posts:

[C#] Dubbele buffering op een andere schaal

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig in C# om onder andere een waveform te tekenen van een wav bestand. Dat is dan ook gelukt, maar nu wil ik het plaatje gebufferd laden. Dat lukt natuurlijk ook wel, maar ik krijg het niet voor elkaar om het in de goede schaal te tekenen.

Zo moet ik het krijgen. Deze is dus goed geschaald, maar niet gebufferd
Afbeeldingslocatie: http://xs101.xs.to/xs101/06214/ongebufferd.PNG

Nu heb ik het bufferen erbij gehaald maar wordt het zo:
Afbeeldingslocatie: http://xs201.xs.to/xs201/06214/gebufferd.PNG
Dat is dus alleen het beginstukje van de complete waveform, omdat het schalen niet lukt.

De code waar het om gaat:
C#:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public void Draw(PaintEventArgs pea, Pen pen)
{
    if( waveLoaded )
    {
        Graphics grfx;

        Bitmap drawing = new Bitmap( (int)pea.Graphics.VisibleClipBounds.Width, 
            (int)pea.Graphics.VisibleClipBounds.Height, pea.Graphics);
        grfx = Graphics.FromImage(drawing);

        grfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;

        // schalen
        if ( panelScale == 0.0f )
            panelScale = grfx.VisibleClipBounds.Width / waveSampleCount;
        grfx.PageScale = panelScale;
        RectangleF visBounds = grfx.VisibleClipBounds;
        grfx.DrawLine( pen, 0, visBounds.Height / 2, visBounds.Width, visBounds.Height / 2 );
        grfx.TranslateTransform( 0, visBounds.Height );
        grfx.ScaleTransform( 1, -1 );

        // van 8 bit naar 16 bit array
        Int16[] waveData16 = new Int16[ waveSampleCount ];
        int j = 0;
        for( int i = 0; i < waveSampleCount; i++ )
        {
            waveData16[i] = (short)(waveData[j++] + (waveData[j++] * 256));
        }

        // lijntje tekenen
        short val = waveData16[ 0 ];
        int prevX = 0;
        int prevY = (int) (( (val + 32768) * visBounds.Height ) / 65536 );
        for ( int i = 0; i < waveSampleCount; i++ )
        {
            val = waveData16[ i ];
            int scaledVal = (int) (( (val + 32768) * visBounds.Height ) / 65536 );
            grfx.DrawLine( pen, prevX, prevY, i, scaledVal );
            prevX = i;
            prevY = scaledVal;
            if ( waveFormat.nChannels == 2 )
                i++;
        }

        pea.Graphics.DrawImageUnscaled(drawing, 0, 0);
        //pea.Graphics.DrawImage(drawing, 0, 0);
        grfx.Dispose();
    }
}
grfx.PageScale (regel 14) krijgt wel de juiste schaal van panelScale, maar als ik daarna grfx.VisibleClipBounds bekijk heeft die nog zijn oude hoogte en breedte. Dat lijkt mij niet helemaal de bedoeling?
Of zet ik bij de verkeerde Graphics instantie de schaal?

Verwijderd

Ik weet niet hoe het in C# geregeld is, maar deze regel:

waveData16[i] = (short)(waveData[j++] + (waveData[j++] * 256));

lijkt me op het eerste gezicht verdacht. Twee maal de ++ operator gebuiker in dezelfde expressie geeft in bijv. C++ undefined behaviour. Misschien heb je hier wat aan.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21-02 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat is in C# gewoon goed gedefinieerd
Operands in an expression are evaluated from left to right. For example, in F(i) + G(i++) * H(i), method F is called using the old value of i, then method G is called with the old value of i, and, finally, method H is called with the new value of i. This is separate from and unrelated to operator precedence.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

L.Mo schreef:
[/code]grfx.PageScale (regel 14) krijgt wel de juiste schaal van panelScale, maar als ik daarna grfx.VisibleClipBounds bekijk heeft die nog zijn oude hoogte en breedte. Dat lijkt mij niet helemaal de bedoeling?
Erhm, de pagescale (ie. de relatie tussen wereldunits en pageunits) van een graphics object veranderen heeft ook helemaal geen invloed op de afmetingen van z'n visible clipbounds rectangle, alleen op de relatieve positie waar pixels getekend worden binnen binnen die bounds.

Verwijderd

Topicstarter
DroogKloot schreef op donderdag 25 mei 2006 @ 17:59:
[...]


Erhm, de pagescale (ie. de relatie tussen wereldunits en pageunits) van een graphics object veranderen heeft ook helemaal geen invloed op de afmetingen van z'n visible clipbounds rectangle, alleen op de relatieve positie waar pixels getekend worden binnen binnen die bounds.
Oh, dat dacht ik. Want als ik er met debug door onderstaande code (zonder tekenbuffer) loop, en ik ga voorbij regel 10, dan set hij de grfx.PageScale op 0.004586356 en veranderd hij de grfx.VisibleClipBounds van
{X=0.0 Y=0.0 Width=526.0 Height=102.0} naar
{X=0.0 Y=0.0 Width=114687.992 Height=22239.877}
C#:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
public void Draw(PaintEventArgs pea, Pen pen)
{
    Graphics grfx = pea.Graphics;

    if( waveLoaded )
    {
        if ( panelScale == 0.0f )
            panelScale = grfx.VisibleClipBounds.Width / waveSampleCount;

        grfx.PageScale = panelScale;

        RectangleF visBounds = grfx.VisibleClipBounds;

        grfx.DrawLine( pen, 0, visBounds.Height / 2, visBounds.Width, visBounds.Height / 2 );

        grfx.TranslateTransform( 0, visBounds.Height );
        grfx.ScaleTransform( 1, -1 );

        Int16[] waveData16 = new Int16[ waveSampleCount ];

        // van 8 bit array naar 16 bit array
        int j = 0;
        for( int i = 0; i < waveSampleCount; i++ )
        {
            waveData16[i] = (short)(waveData[j++] + (waveData[j++] * 256));
        }

        short val = waveData16[ 0 ];

        int prevX = 0;
        int prevY = (int) (( (val + 32768) * visBounds.Height ) / 65536 );

        for ( int i = 0; i < waveSampleCount; i++ )
        {
            val = waveData16[ i ];

            int scaledVal = (int) (( (val + 32768) * visBounds.Height ) / 65536 );

            grfx.DrawLine( pen, prevX, prevY, i, scaledVal );

            prevX = i;
            prevY = scaledVal;

            if ( waveFormat.nChannels == 2 )
                i++;
        }
    }
}
Maar dat gebeurd niet in de code die ik eerder heb gepost ;(

Verwijderd

Topicstarter
Ok, de code die ik hierboven heb gepost werkt dus goed maar tekent niet gebufferd. Dus ik dacht om in plaats van het bufferen in de functie te zetten, de Graphics van de buffer aan de functie mee te geven, zodat hij daarop tekent.

C#:
1
2
3
4
5
6
7
8
9
private void display_A_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    Bitmap BackBuffer = new Bitmap((int)e.Graphics.VisibleClipBounds.Width, (int)e.Graphics.VisibleClipBounds.Height);
    Graphics BufferGraphics = Graphics.FromImage(BackBuffer);

    playerA.Draw(BufferGraphics);

    e.Graphics.DrawImageUnscaled(BackBuffer, 0, 0);
}
Dit moet een nieuwe bitmap aanmaken en dan de Graphics daarvan net zo doorgeven aan Draw() als dat hij die normaal uit de PaintEventArgs zou krijgen.

Dat lukt ook, maar weer zet hij de VisibleClipBounds niet...

Iemand een idee hoe ik het dan nog zou kunnen proberen?

Verwijderd

Topicstarter
kick
Pagina: 1