RenderTargetBitmap呈现一个大小错误的图像 [英] RenderTargetBitmap renders image of a wrong size

查看:2266
本文介绍了RenderTargetBitmap呈现一个大小错误的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的任务是向用户展示他的XPS文档的每个页面的缩略图。我需要所有的图像要小,所以我使他们的 DPI 的设置为72.0(我GOOGLE了一张A4纸的大小是与DPI 72.0为635x896)。基本上,我做到以下几点:

My task is to show the user a thumbnail of each page of his XPS document. I need all the images to be small, so I render them with dpi set to 72.0 (I have googled that size of an A4 sheet with dpi 72.0 is 635x896). Basically, I do the following:

        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)和图像的规模不断壮大更大的(我猜,我只是不太undrestand什么dpi是,它如何影响文档)。我试图让的 DPI = 96.0 的,而且规模小了。我设置一张图片来自的BitmapImage 的代码生成上面来源为图片类的实例集合控制(我创建一个WPF应用程序),并在情况下,DPI设置为96.0我的程序是这样的:

But when I render a document page (A4) its size is actually 846x1194 instead of the one I expected. I tried to make the dpi lower (48.0) and the image's size has grown even bigger (I guess, I just do not quite undrestand what dpi is and how it affects the document). I tried to make dpi=96.0, and the size went smaller. I set one of images from the collection of instances of the class BitmapImage generated by the code above as source for the Image control (I am creating a WPF application) and in case dpi is set to 96.0 my program looks like this:

结果
你可以看到,页面的部分不显示在所有的,它不适合图片控制,即使控制的大小设置为 635x896 的,这就是为什么根据上面的代码,图像必须正确显示和所有的文字必须符合。结果
我期待什么结果,概括地说:我想创建一个文档页面的缩略图,但我希望他们能较小,相对于一些数字(我很抱歉,我不太知道怎么做我用英语说这样的东西,基本上如果文档的页面宽度为1200像素,我希望它是 1200 / N ,其中的 N 的就是我前面提到的)一定数量,但如果收缩图像的大小仍比更大的 635x896 的我想要的大小为的 635x896 的。结果
在此先感谢。同时,我为我的英语不好对不起。


As you can see, part of the page is not shown at all, it does not fit inside the Image control, even though the size of the control is set to 635x896 that's why according to the code above, the image must be displayed correctly and all the text must fit.
What result do I expect in a nutshell: I am trying to create thumbnails of the pages of a document, but I want them to be smaller, relative to some number (I am sorry, I am not quite sure how do I say such stuff in English, basically if the document's page width is 1200 px I want it to be 1200/n, where n is the "some number" that I mentioned earlier), but if the shrinked image's size is still bigger than 635x896 I want the size to be 635x896.
Thanks in advance. And also I am sorry for my bad English.

推荐答案

首先,DPI是指每英寸点数,或每英寸的像素。在渲染一张A4纸的情况下 - 这是21 29.7厘米3 - 在72 DPI位图,你最终会得到以下尺寸的位图:

First of all, DPI means Dots Per Inch, or pixel per inch. In the case of rendering an A4 page - which is 21 by 29.7 cm - to a bitmap at 72 DPI, you would end up with a bitmap of the following size:


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

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

除了这个你不应该太在意DPI,但有一个例外:WPF渲染是在做96 DPI。这意味着您的文档的A4大小的页面渲染到794点¯x1123位图。作为一个提醒:

Besides this you shouldn't care too much about DPI, with one exception: WPF rendering is done at 96 DPI. This means that an A4-sized page of your document is rendered to a 794 x 1123 bitmap. As a reminder:


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

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

因此, 794点¯x1123应该是你RenderTargetBitmap的大小时,它包含一个页面,这正是A4。如果页面大小小于A4,位图应较小。如果另一方面页是大于A4的,它应该是的缩小的到794点¯x1123这就是诀窍。而不是直接渲染页面的视觉进入RenderTargetBitmap的,你可以把视觉到 ContainerVisual ,提供一个 ScaleTransform 的,如下所示。

Hence, 794 x 1123 should be the size of your RenderTargetBitmap when it contains a page that is exactly A4. If the page size is less than A4, the bitmap should be smaller. If on the other hand the page is larger than A4, it should be scaled down to 794 x 1123. And that is the trick. Instead of rendering the page visual directly into the RenderTargetBitmap, you can put the visual into a ContainerVisual with a ScaleTransform as shown below.

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);

    ...
}

这篇关于RenderTargetBitmap呈现一个大小错误的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆