2009-03-13 16 views
6

Quando visualizzo un JPEG nella mia applicazione WPF (usando il seguente codice), è mostrato significativamente più piccolo di se apro il JPEG nel Visualizzatore immagini di Windows in tempo reale dimensione.L'immagine all'interno di un'applicazione WPF è più piccola di quando visualizzata nel visualizzatore esterno

Ho forato nelle proprietà della mia ImageSource in fase di esecuzione e la mia immagine ha:

  • un DPI di 219
  • un'altezza di 238,02739726027397
  • una larghezza di 312,54794520547944
  • un PixelHeight di 543
  • e PixelWidth di 713

Quando uso un righello dello schermo per misurare il display WPF dell'immagine, ottengo ca. 313x240 pixel (che se potessi posizionare il righello perfettamente sarebbe probabilmente uguale alla larghezza e all'altezza che ImageSource sta segnalando).

Il mio istinto mi dice che questo ha qualcosa a che fare con l'uso di unità indipendenti dal dispositivo (anziché pixel), ma non riesco a capirlo, e ho ancora bisogno di sapere come visualizzare l'immagine all 'attuale 'dimensione di 543x713 nella mia applicazione.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Height="300" Width="300"> 
    <StackPanel> 
     <Image Source="Image15.jpg" Stretch="None" /> 
    </StackPanel> 
</Window> 

risposta

4

Utilizzare un DPI di 96. WPF è scalare l'immagine in base alle dimensioni in pollici, mentre il visualizzatore di immagini è la visualizzazione pixel. Sulla maggior parte dei sistemi Windows, si presume che la risoluzione dello schermo sia di 96 DPI, quindi l'utilizzo di tale immagine risulterà in una traduzione uno-a-uno.

+0

Se qualcuno ha bisogno di uno strumento per il DPI correzione: è possibile utilizzare [Paint.NET] (http://www.getpaint.net), che è gratuito e facile da usare per questo scopo. – Beauty

1

Questo è il risultato del file .jpg stesso che specifica DPI - WPF sta semplicemente obbedendo. Here is a forum post descrivendo il problema con alcune soluzioni:

8

Grazie Mark! Ho fatto un po 'su Google in base alle tue informazioni e ho trovato this article che ha fornito una soluzione per ottenere il risultato che volevo. Questo sta cominciando ad avere senso ora ...

Modifica: Linkrot. Incollare il testo critico dal l'articolo qui per riferimento ....

<Image Source=”{Binding …}” 
     Stretch=”Uniform” 
     Width=”{Binding Source.PixelWidth,RelativeSource={RelativeSource Self}}” 
     Height=”{Binding Source.PixelHeight,RelativeSource={RelativeSource Self}}” /> 

Qui abbiamo impostato Stretch per uniforme e legati la larghezza e l'altezza al PixelWidth e> PixelHeight della Fonte, in modo efficace ignorando DPI. L'immagine tuttavia non sarà pixel> perfetta, anche quando si utilizza SnapToDevicePixels (che semplicemente scatta i bordi, non i pixel> all'interno dell'immagine). Tuttavia, WPF in 3.5 SP1 supporterà un NearestNeighbor> BitmapScalingMode, che dovrebbe correggere questo.

+0

Utilizzati in una MultiBinding per archiviare il Tag del controllo immagine per uso futuro, grazie! –

+0

Il ** BitmapScalingMode ** è possibile applicare in questo modo: '' – Beauty

3

In alternativa, si potrebbe estendere immagine e implementare MeasureOverride e ArrangeOverride per cambiare l'effetto del DPI dell'immagine:

class DpiAgnosticImage : Image 
{ 
    protected override Size MeasureOverride(Size constraint) 
    { 
     var bitmapImage = Source as BitmapImage; 

     var desiredSize = bitmapImage == null 
      ? base.MeasureOverride(constraint) 
      : new Size(bitmapImage.PixelWidth, bitmapImage.PixelHeight); 

     var dpiScale = MiscUtil.GetDpiScale(this); 
     desiredSize = new Size(desiredSize.Width/dpiScale.Width, desiredSize.Height/dpiScale.Height); 

     desiredSize = ImageUtilities.ConstrainWithoutDistorting(desiredSize, constraint); 

     if (UseLayoutRounding) 
     { 
      desiredSize.Width = Math.Round(desiredSize.Width); 
      desiredSize.Height= Math.Round(desiredSize.Height); 
     } 

     return desiredSize; 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     return new Size(Math.Round(DesiredSize.Width), Math.Round(DesiredSize.Height)); 
    } 
} 

usarlo in XAML come se si trattasse di un'immagine:

<Grid> 
    <local:DpiAgnosticImage 
    Stretch="None" 
    Source="{Binding ViewImage}"> 
    <Image.RenderTransform> 
     <ScaleTransform 
     x:Name="SomeName"/> 
    </Image.RenderTransform> 
    </local:DpiAgnosticImage> 
</Grid> 

Flaws al codice di cui sopra (che io sappia):

  • ignora Stretch
  • Assume Source è un BitmapImage

=== Modifica - il commento di Will suggerisce che vorrebbe sapere che cosa è in GetDpiScale()

public static Size GetDpiScale(Visual visual) 
    { 
     var source = PresentationSource.FromVisual(visual); 

     var dpiScale = new Size(
      source.CompositionTarget.TransformToDevice.M11, 
      source.CompositionTarget.TransformToDevice.M22); 

     return dpiScale; 
    } 
+0

MiscUtil? Utile. – Will