【问题标题】:RenderTargetBitmap renders image of a wrong sizeRenderTargetBitmap 渲染错误大小的图像
【发布时间】:2012-10-20 02:59:04
【问题描述】:

我的任务是向用户显示其 XPS 文档每一页的缩略图。我需要所有图像都变小,所以我将它们渲染为 dpi 设置为 72.0(我用谷歌搜索了 dpi 72.0 的 A4 纸的尺寸是 635x896)。基本上,我会执行以下操作:

        List<BitmapImage> thumbnails = new List<BitmapImage>();
        documentPaginator.ComputePageCount();
        int pageCount = documentPaginator.PageCount;
        for (int i = 0; i < pageCount; i++)
        {
            DocumentPage documentPage = documentPaginator.GetPage(i);
            bool isLandscape = documentPage.Size.Width > documentPage.Size.Height;
            Visual pageVisual = documentPage.Visual;
            //I want all the documents to be less or equals to A4
            //private const double A4_SHEET_WIDTH = 635;
            //private const double A4_SHEET_HEIGHT = 896;
            //A4 sheet size in px, considering 72 dpi
            RenderTargetBitmap targetBitmap = new RenderTargetBitmap(
            (int)(System.Math.Min(documentPage.Size.Width, A4_SHEET_WIDTH)),
            (int)(System.Math.Min(documentPage.Size.Height, A4_SHEET_HEIGHT)),
            72.0, 72.0,
            PixelFormats.Pbgra32);
            targetBitmap.Render(pageVisual);
            BitmapFrame frame = BitmapFrame.Create(targetBitmap);
            PngBitmapEncoder encoder = new PngBitmapEncoder();
            encoder.Frames.Add(frame);
            BitmapImage image = new BitmapImage();
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                encoder.Save(ms);
                image.BeginInit();
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.StreamSource = ms;
                if (isLandscape)
                {
                    image.Rotation = Rotation.Rotate270;
                }
                image.EndInit();
            }
            thumbnails.Add(image);
        }

但是当我渲染一个文档页面 (A4) 时,它的大小实际上是 846x1194 而不是我预期的。我试图降低 dpi (48.0) 并且图像的尺寸变得更大(我想,我只是不太明白 dpi 是什么以及它如何影响文档)。我尝试制作dpi=96.0,尺寸变小了。我将上面代码生成的类BitmapImage 的实例集合中的一个图像设置为Image 控件的源(我正在创建一个WPF 应用程序),如果dpi 设置为96.0,我的程序看起来像这样:


如您所见,页面的一部分根本没有显示,它不适合Image 控件,即使控件的大小设置为 635x896 这就是为什么根据代码以上,图片必须正确显示,所有文字必须适合。
简而言之,我期望什么结果:我正在尝试创建文档页面的缩略图,但我希望它们相对于某个数字更小(对不起,我不太确定我该怎么说这些东西用英文,基本上如果文档的页面宽度是 1200 px,我希望它是 1200/n,其中 n 是我前面提到的“某个数字”),但如果缩小图像的大小仍然大于 635x896 我希望尺寸为 635x896
提前致谢。我也很抱歉我的英语不好。

【问题讨论】:

    标签: c# wpf image thumbnails dpi


    【解决方案1】:

    首先,DPI 表示每英寸点数,或每英寸像素。如果将 A4 页面(21 x 29.7 厘米)渲染为 72 DPI 的位图,您最终会得到以下大小的位图:

    • 宽度 = 21 厘米/(2.54 厘米/英寸)* 72 像素/英寸 = 595 像素
    • 高度 = 29.7 厘米/(2.54 厘米/英寸)* 72 像素/英寸 = 842 像素

    除此之外,您不必太在意 DPI,但有一个例外:WPF 渲染以 96 DPI 完成。这意味着文档的 A4 大小页面将呈现为 794 x 1123 位图。提醒一下:

    • 宽度 = 21 厘米/(2.54 厘米/英寸)* 96 像素/英寸 = 794 像素
    • 高度 = 29.7 厘米/(2.54 厘米/英寸)* 96 像素/英寸 = 1123 像素

    因此,794 x 1123 应该是您的 RenderTargetBitmap 的大小,当它包含一个正好是 A4 的页面时。如果页面大小小于 A4,则位图应该更小。另一方面,如果页面大于 A4,则应将其缩小至 794 x 1123。这就是诀窍。无需将页面视觉对象直接渲染到 RenderTargetBitmap 中,您可以将视觉对象放入 ContainerVisualScaleTransform 中,如下所示。

    for (int i = 0; i < paginator.PageCount; i++)
    {
        DocumentPage page = paginator.GetPage(i);
        double width = page.Size.Width;
        double height = page.Size.Height;
        double maxWidth = Math.Round(21.0 / 2.54 * 96.0); // A4 width in pixels at 96 dpi
        double maxHeight = Math.Round(29.7 / 2.54 * 96.0); // A4 height in pixels at 96 dpi
        double scale = 1.0;
        scale = Math.Min(scale, maxWidth / width);
        scale = Math.Min(scale, maxHeight / height);
    
        ContainerVisual containerVisual = new ContainerVisual();
        containerVisual.Transform = new ScaleTransform(scale, scale);
        containerVisual.Children.Add(page.Visual);
    
        RenderTargetBitmap bitmap = new RenderTargetBitmap(
            (int)(width * scale), (int)(height * scale), 96, 96, PixelFormats.Default);
    
        bitmap.Render(containerVisual);
    
        ...
    }
    

    【讨论】:

    • 非常感谢!现在一切都清楚了。如果可以的话,我会至少给你的答案投票 10 次。
    • 有没有办法让 A4 缩略图变小?我尝试更改 DPI,但它似乎不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 2017-09-01
    • 2019-03-17
    相关资源
    最近更新 更多