2012-03-21 7 views
5

enter image description herecome rendere il pennello liscio senza linee in mezzo

Ciao a tutti, come vedete nella spazzola precedente c'è linee in mezzo,
non è così liscia come rendere liscia? (Come rimuovere che linee) genero con miscela

<Grid x:Name="LayoutRoot"> 
     <Grid.Background> 
      <LinearGradientBrush EndPoint="0.452,1.962" StartPoint="1.164,-0.352"> 
       <GradientStop Color="#FF202020" Offset="0"/> 
       <GradientStop Color="#FF545454" Offset="1"/> 
      </LinearGradientBrush> 
     </Grid.Background> 
    </Grid> 
+0

Puoi pubblicare il tuo codice che sta creando il pennello. È un pennello sfumato? – ChrisF

+0

ok puoi controllare il codice ora. –

risposta

9

Il bendaggio è un artefatto del algoritmo del gradiente. Deve rompere l'area in bande ciascuna riempita con un colore leggermente diverso. I bordi sono in realtà un'illusione ottica che ha l'effetto di renderli più visibili di quanto si pensi. Per ridurre questo effetto è necessario ridurre la larghezza di ogni banda.

Le soluzioni sono:

  1. Riempire su un'area più piccola - ogni banda è più stretta.
  2. Aumentare il numero di bande. Rendi più ampio il contrasto tra i due estremi.
  3. Aumentare la risoluzione del colore del display. Se hai più colori tra cui scegliere, ci sarà un intervallo utilizzabile più ampio tra i due colori finali.

Mi rendo conto che queste soluzioni sono a) non possibili o b) non pratiche. Questo è un problema con cui dovrai convivere.

Una soluzione pratica potrebbe essere quella di sostituire il pennello con un'immagine creata in Photoshop o un altro pacchetto di elaborazione immagini. Questo potrebbe darti un'immagine con meno banding - ma poi sei limitato alle dimensioni dell'immagine - non puoi farcela senza pixelation.

+0

grazie mille. –

8

Qualche tempo fa ho scritto una sfumatura lineare uniforme per il mio progetto WPF. Rimuove il banding, ma sono presenti due avvertimenti:

  • Non può essere utilizzato per i colori dei databound o {DynamicResource}.
  • Attualmente supporta solo il gradiente verticale, come che era tutto il necessario

E 'implementato come dynamicly creato ImageBrush, utilizzando Ordered Dithering. Inoltre, è anche un MarkupExtension, poiché non è possibile ereditare semplicemente una qualsiasi classe Brush (sono tutte sigillate).

/// <summary> 
/// Brush that lets you draw vertical linear gradient without banding. 
/// </summary> 
[MarkupExtensionReturnType(typeof(Brush))] 
public class SmoothLinearGradientBrush : MarkupExtension 
{ 
    private static PropertyInfo dpiX_; 
    private static PropertyInfo dpiY_; 
    private static byte[,] bayerMatrix_ = 
    { 
     { 1, 9, 3, 11 }, 
     { 13, 5, 15, 7 }, 
     { 1, 9, 3, 11 }, 
     { 16, 8, 14, 6 } 
    }; 

    static SmoothLinearGradientBrush() 
    { 
     dpiX_ = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static); 
     dpiY_ = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static); 
    } 

    /// <summary> 
    /// Gradient color at the top 
    /// </summary> 
    public Color From { get; set; } 

    /// <summary> 
    /// Gradient color at the bottom 
    /// </summary> 
    public Color To { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     //If user changes dpi/virtual screen height during applicaiton lifetime, 
     //wpf will scale the image up for us. 
     int width = 20; 
     int height = (int)SystemParameters.VirtualScreenHeight; 
     int dpix = (int)dpiX_.GetValue(null); 
     int dpiy = (int)dpiY_.GetValue(null); 


     int stride = 4 * ((width * PixelFormats.Bgr24.BitsPerPixel + 31)/32); 

     //dithering parameters 
     double bayerMatrixCoefficient = 1.0/(bayerMatrix_.Length + 1); 
     int bayerMatrixSize = bayerMatrix_.GetLength(0); 

     //Create pixel data of image 
     byte[] buffer = new byte[height * stride]; 

     for (int line = 0; line < height; line++) 
     { 
      double scale = (double)line/height; 

      for (int x = 0; x < width * 3; x += 3) 
      { 
       //scaling of color 
       double blue = ((To.B * scale) + (From.B * (1.0 - scale))); 
       double green = ((To.G * scale) + (From.G * (1.0 - scale))); 
       double red = ((To.R * scale) + (From.R * (1.0 - scale))); 

       //ordered dithering of color 
       //source: http://en.wikipedia.org/wiki/Ordered_dithering 
       buffer[x + line * stride] = (byte)(blue + bayerMatrixCoefficient * bayerMatrix_[x % bayerMatrixSize, line % bayerMatrixSize]); 
       buffer[x + line * stride + 1] = (byte)(green + bayerMatrixCoefficient * bayerMatrix_[x % bayerMatrixSize, line % bayerMatrixSize]); 
       buffer[x + line * stride + 2] = (byte)(red + bayerMatrixCoefficient * bayerMatrix_[x % bayerMatrixSize, line % bayerMatrixSize]); 
      } 
     } 

     var image = BitmapSource.Create(width, height, dpix, dpiy, PixelFormats.Bgr24, null, buffer, stride); 
     image.Freeze(); 
     var brush = new ImageBrush(image); 
     brush.Freeze(); 
     return brush; 
    } 
} 

Utilizzo in dizionario risorse:

<local:SmoothLinearGradientBrush x:Key="WindowBackgroundBrush" 
           From="{StaticResource WindowBackgroundColorLight}" 
           To="{StaticResource WindowBackgroundColorDark}" /> 

e poi in stile controllo:

<Style ...> 
    <Setter Property="Background" Value="{StaticResource WindowBackgroundBrush}" /> 
</Style> 
0

Una soluzione economica e sporca da un'altra risposta di mia è questa:

Add il gradiente di un contenitore, dargli un piccolo margine negativo in modo che si rovesci un po ', aggiungere un BlurEffect a il gradiente e quindi attivare ClipToBounds sul contenitore padre. In questo modo il gradiente si uniforma leggermente a scapito delle prestazioni.

A seconda del caso d'uso, questo potrebbe non essere fattibile, tuttavia.

Esempio:

<Grid Height="26" Margin="-5,0" ClipToBounds="True"> 
    <Grid Margin="-5"> 
     <Grid.Effect> 
      <BlurEffect Radius="6" /> 
     </Grid.Effect> 
     <Grid.Background> 
      <LinearGradientBrush> 
       <GradientStop x:Name="GradientStop7" Color="Magenta" Offset="0.0" /> 
       <GradientStop x:Name="GradientStop8" Color="DarkOrchid" Offset=".2" /> 
       <GradientStop x:Name="GradientStop9" Color="Purple" Offset="1" /> 
      </LinearGradientBrush> 
     </Grid.Background> 
    </Grid> 
</Grid> 

Il gradiente negativo deve essere uguale al raggio di sfocatura in modo che esso non diventa trasparente sui bordi.

Problemi correlati