none
WPF-C# : problema con WriteableBitmap RRS feed

  • Discussione generale

  • Salve a tutti,

    per prima cosa mi scuso se questo non è il forum giusto nel quale postare questa domanda.

    Spero qualcuno mi sappia aiutare perchè questo problemino mi sta davvero facendo impazzire :P

    Quello che praticamente sto provando a fare (in realtà è il primo passo) è quello di portare l'applicazione di Renè Shulte da Silverlight a WPF

    http://kodierer.blogspot.com/2009/05/oscar-algorithm-silverlight-real-time.html

     

    Il problema che ho, è nell'utilizzo della writeableBitmap (che ha metodi e costruttore diversi rispetto alla classe implementata in SL) :

    "creo" il seguente xaml (una mera "conversione" in wpf di quello fatto da Shulte)

    <Window
    	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    	x:Class="PN_WPF.MainWindow"
    	x:Name="Window"
    	Title="MainWindow"
    	Width="640" Height="518">
    
    	<Grid x:Name="LayoutRoot" Background="White" Margin="0,0,0,-55">
          <StackPanel Width="512" Margin="56,10,56,8">
          <TextBlock HorizontalAlignment="Center" FontSize="14" Text="Real-time computed 3D Perlin Noise" />
          <Image Width="256" Height="256" Name="ImgNoise" Stretch="UniformToFill" />
          <TextBlock Name="TxtFps" HorizontalAlignment="Center" Text="FPS" />
          <Grid Name="GrdParams" >
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="80" />
              <ColumnDefinition />
              <ColumnDefinition Width="60" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
              <RowDefinition />
              <RowDefinition />
              <RowDefinition />
              <RowDefinition />
              <RowDefinition />
              <RowDefinition />
              <RowDefinition />
            </Grid.RowDefinitions>
            
            <TextBlock Grid.Column="0" Grid.Row="0" Text="Frequency" VerticalAlignment="Center" />
            <Slider Grid.Column="1" Grid.Row="0" Minimum="0" Maximum="0.25" SmallChange="0.001" Value="{Binding Mode=TwoWay, Path=Frequency}" ValueChanged="FreqSlider_ValueChanged" />
            <TextBlock Name="TxtFreq" Grid.Column="2" Grid.Row="0" />
            
            <TextBlock Grid.Column="0" Grid.Row="1" Text="Amplitude" VerticalAlignment="Center" />
            <Slider Grid.Column="1" Grid.Row="1" Minimum="0" Maximum="16" SmallChange="0.1" Value="{Binding Mode=TwoWay, Path=Amplitude}" ValueChanged="AmpSlider_ValueChanged" />
            <TextBlock Name="TxtAmp" Grid.Column="2" Grid.Row="1" />
            
            <TextBlock Grid.Column="0" Grid.Row="2" Text="Persistence" VerticalAlignment="Center" />
            <Slider Grid.Column="1" Grid.Row="2" Minimum="0" Maximum="1" SmallChange="0.001" Value="{Binding Mode=TwoWay, Path=Persistence}" ValueChanged="PersSlider_ValueChanged" />
            <TextBlock Name="TxtPers" Grid.Column="2" Grid.Row="2" />
            
            <TextBlock Grid.Column="0" Grid.Row="3" Text="Octaves" VerticalAlignment="Center" />
            <Slider Grid.Column="1" Grid.Row="3" Minimum="1" Maximum="32" SmallChange="1" LargeChange="1" Value="{Binding Mode=TwoWay, Path=Octaves}" ValueChanged="OctSlider_ValueChanged" />
            <TextBlock Name="TxtOct" Grid.Column="2" Grid.Row="3" />
    
            <TextBlock Grid.Column="0" Grid.Row="4" Text="BaseColor" VerticalAlignment="Center" />
            <StackPanel Margin="0,5,0,0" Orientation="Horizontal" Grid.Column="1" Grid.Row="4">
              <TextBox Text="#FF000000" Name="TxtBaseColor" Width="100" TextChanged="TxtBaseColor_TextChanged" />
              <TextBlock Margin="20,0" Text="(LightBlue: #FFADD8E6)" VerticalAlignment="Center" />
             </StackPanel>
    
            <TextBlock Grid.Column="0" Grid.Row="5" Text="NoiseColor" VerticalAlignment="Center" />
            <StackPanel Margin="0,5,0,0" Orientation="Horizontal" Grid.Column="1" Grid.Row="5">
              <TextBox Text="#FFFFFFFF" Name="TxtNoiseColor" Width="100" TextChanged="TxtNoiseColor_TextChanged" />
              <TextBlock Margin="20,0" Text="" VerticalAlignment="Center" />
            </StackPanel>
    
            <StackPanel Margin="0,5,0,0" Orientation="Horizontal" Grid.Column="1" Grid.Row="6">
              <Button Content="Randomize" Width="100" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="Button_Click"/>
              <CheckBox Name="Chk3D" Margin="20,0" IsChecked="True" Content="3D (Animation)" VerticalAlignment="Center" />
            </StackPanel>
    
          </Grid>
        </StackPanel>
      </Grid>
    	
    </Window>

    nel quale ho una Immagine 256x256. Tale immagine deve essere praticamente una texture procedurale quindi nel MainWindow.xaml.cs creo un writeablebitmap che "poi" associo alla ImgNoise definita nello xaml:

    // Init WriteableBitmap
    


    writeableBmp =
    new
    WriteableBitmap(
    TextureSize,
    TextureSize,
    96.0d,
    96.0d,
    PixelFormats.Gray8,
    null
    );

    this
    .ImgNoise.Source = this
    .writeableBmp;


    Quindi alla pressione del bottone Randomize richiamo una funzione Render, così implementata

      private void render()
        {
          // Calculate Perlin Noise image and invalidate
          int index = 0;
    
          int stride = TextureSize * ((writeableBmp.Format.BitsPerPixel + 7) / 8); 
          int arraySize = TextureSize * stride;
          byte[] pixels = new byte[arraySize];
    
          
          for (int y = 0; y < writeableBmp.PixelHeight; y++)
          {
            for (int x = 0; x < writeableBmp.PixelWidth; x++)
            {
              float a = perlinNoise.Compute(TextureSize - x,TextureSize - y, perlinZ);
              float ai = 1 - a;
              byte e = (byte)(a * noiseColor.A + ai * baseColor.A);
              byte f = (byte)(a * noiseColor.R + ai * baseColor.R);
              byte j = (byte)(a * noiseColor.G + ai * baseColor.G);
              byte h = (byte)(a * noiseColor.B + ai * baseColor.B);
    
              e = (byte)(e << 24);
              f = (byte)(f << 16);
              j = (byte)(j << 8);
              if ((pixels[index] + (byte)(e | f | j | h)) > 255)
                pixels[index++] = 255;
              else
                pixels[index++] += (byte)(e | f | j | h);
    
              
            }
          }
          /*
    
          for(int i=0;i<pixels.Length;i++)
          {
            pixels[i] = CloudExpCurve(pixels[i]); 
          }
          */
    
          // Set up the source rect.
          Int32Rect rect = new Int32Rect(0, 0, (int)writeableBmp.Width, (int)writeableBmp.Height);
    
          // Send the pixel array to the rendering system. 
          writeableBmp.WritePixels(rect, pixels, stride, 0);
    
          /*
          if(Chk3D.IsChecked.Value)
          {
            perlinZ++;
          }*/
    
          // writeableBmp.Invalidate();
       
        }
    

    Ora, finchè io utilizzo la writeableBitmap creata con

    PixelFormats.Gray8



    La bitmap creata occupa tutta la superficie di ImgNoise, ottenendo cosi una texture avendo colori definiti su una scala di grigi.

    Però, dato che a me serve poter utilizzare altri colori, oltre i grigi, provo a dichiarare la writeablebitmap così

     

    // Init WriteableBitmap
    

    writeableBmp = new
    WriteableBitmap(
    TextureSize,
    TextureSize,
    96.0d,
    96.0d,
    PixelFormats.Bgra32,
    null

    );



     

    A questo punto però la texture ImgNoise è composta da 4 piccole textures ce occupano solo "1 riga" di ImgNoise, mentre quello che mi interessa ottenere è una texture procedurale grande quanto la dimensione di ImgNoise(256*256) a colori.

    Vi posto se possono essere utili (ai fini della comprensione del problema) queste due immagini :

    OK_maScalaDiGrigi

    http://img831.imageshack.us/i/immagine1m.jpg/

    NON_BUONO_colori

    http://img199.imageshack.us/i/immagine2xq.jpg/

    Mentre l'applicazione completa è scaricabile da

    http://www.megaupload.com/?d=SN9BCR2G

     

    Spero qualcuno sappia aiutarmi.

    Grazie e buona giornata a tutti

     

    giovedì 22 luglio 2010 08:54