WPF 框架設計爲與 DPI 無關,但你依然可能遇到 DPI 問題。尤其是 Image 控件顯示的圖片會根據圖片 EXIF 中的 DPI 信息和屏幕 DPI 自動縮放圖片。對於 UI 用圖來說這是好事,但對於軟件用戶隨便插入的圖片來說就不是了——用戶傳入的圖片可能是各種各樣不統一的 DPI。因此這種 DPI 我們應該忽略。

解決方法

直接設置 Image 控件的大小是一個不錯的方案,這在允許設置 Image 控件大小的場合下是可以使用的。如果你能設置,那麼直接設置,這是最好的方法了。

除此之外,我們還可能可以嘗試這些方法:

  1. 創建 BitmapImage 對象,根據當前屏幕的 DPI 值計算 DecodePixelWidthDecodePixelHeight
  2. 創建 DrawingImage 對象,直接按照 WPF 的座標單位繪製圖片原始像素大小的圖片;
  3. 創建 Bitmap / WriteableBitmap 對象,重新創建一張 96 DPI 的圖片。

以下的代碼中,都假設當前 DPI 的值爲 monitorDpi

DrawingImage

DrawingImage 可以使用 WPF 的方式來繪製,不過如果要繪製位圖,也需要一個 BitmapImage 對象,不過這個時候我們可以按照我們需要的尺寸進行繪製而不用關心 DPI 的問題。由於尺寸是在繪製的時候確定的,所以不需要 Image 控件也設置尺寸。

private static ImageSource CreateBitmapImage(Stream sourceStream)
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.StreamSource = sourceStream;
    bitmap.EndInit();

    var image = new ImageDrawing(
        bitmap,
        new Rect(0, 0, bitmap.PixelWidth / monitorDpi.FactorX, bitmap.PixelHeight / monitorDpi.FactorY));
    var drawing = new DrawingImage(image);
    return drawing;
}

相關文章