【问题标题】:Blurry image when converting DOC to PNG将 DOC 转换为 PNG 时图像模糊
【发布时间】:2018-03-21 12:36:55
【问题描述】:

好的,我有一个问题再次让我感到困惑。我有一些将 DOC 文件转换为 PNG 文件的代码。当我在本地主机上执行此操作时,图像很好。当我采用相同的代码并将其放在实时服务器上时,图像非常小(与我从中获取 DOC 文件的 DOT 文件大小相同,基本上 DOT 被填写并变成了 DOC)。现在......这是疯狂的部分。如果我以管理员身份登录托管服务器,然后访问实时网站,即使我从 iPhone 访问该网站,图像也会大而清晰。一旦我退出托管服务器并刷新实时页面,图像就会再次变小。这是我用来将 DOC 转换为 PNG 的代码。顺便说一句,如果我使用方法2,我可以使图像更大更高分辨率,但字体不合适。

    private void ConvertDocToPNG(string startupPath, string filename1)
    {
        var docPath = Path.Combine(startupPath, filename1);
        Application app = new Application();
        Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document();
        app.Visible = false;
        doc = app.Documents.Open(docPath);
        app.WindowState = Microsoft.Office.Interop.Word.WdWindowState.wdWindowStateMaximize;
        app.ActiveWindow.ActivePane.View.Zoom.Percentage = 100;
        doc.ShowGrammaticalErrors = false;
        doc.ShowRevisions = false;
        doc.ShowSpellingErrors = false;

        //Opens the word document and fetch each page and converts to image
        foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows)
        {
            foreach (Microsoft.Office.Interop.Word.Pane pane in window.Panes)
            {
                for (var i = 1; i <= pane.Pages.Count; i++)
                {
                    Microsoft.Office.Interop.Word.Page page = null;
                    bool populated = false;
                    while (!populated)
                    {
                        try
                        {
                            // This !@#$ variable won't always be ready to spill its pages. If you step through
                            // the code, it will always work.  If you just execute it, it will crash.  So what
                            // I am doing is letting the code catch up a little by letting the thread sleep
                            // for a microsecond.  The second time around, this variable should populate ok.
                            page = pane.Pages[i];
                            populated = true;
                        }
                        catch (COMException ex)
                        {
                            Thread.Sleep(1);
                        }
                    }
                    var bits = page.EnhMetaFileBits;
                    var target = Path.Combine(startupPath + "\\", string.Format("{1}_page_{0}", i, filename1.Split('.')[0]));

                    try
                    {
                        using (var ms = new MemoryStream((byte[])(bits)))
                        {
                            var image = System.Drawing.Image.FromStream(ms);
                            var pngTarget = Path.ChangeExtension(target, "png");

                            // Method 2
                            image.Save(pngTarget, System.Drawing.Imaging.ImageFormat.Png);

                            // Another way to save it using custom size
                            //float width = Convert.ToInt32(hfIdCardMaxWidth.Value);
                            //float height = Convert.ToInt32(hfIdCardMaxHeight.Value);
                            //float scale = Math.Min(width / image.Width, height / image.Height);
                            //int resizedWidth = (int)Math.Round(image.Width * scale);
                            //int resizedHeight = (int)Math.Round(image.Height * scale);
                            //Bitmap myBitmap = new Bitmap(image, new Size(resizedWidth, resizedHeight));
                            //myBitmap.Save(pngTarget, System.Drawing.Imaging.ImageFormat.Png);
                        }
                    }
                    catch (System.Exception ex)
                    {
                        doc.Close(true, Type.Missing, Type.Missing);
                        Marshal.ReleaseComObject(doc);
                        doc = null;
                        app.Quit(true, Type.Missing, Type.Missing);
                        Marshal.ReleaseComObject(app);
                        app = null;
                        throw ex;
                    }
                }
            }
        }
        doc.Close(true, Type.Missing, Type.Missing);
        Marshal.ReleaseComObject(doc);
        doc = null;
        app.Quit(true, Type.Missing, Type.Missing);
        Marshal.ReleaseComObject(app);
        app = null;
    }

【问题讨论】:

  • 假设您希望此代码以无人值守的方式运行是否安全?以这种方式使用 Word 互操作(或任何 MS office 互操作)是一个坏主意,但我们可以使用 OpenXML SDK 为您做一些事情。如果此代码以交互方式运行,则忽略此注释:)
  • 确实是无人值守的时尚。

标签: c# asp.net office-interop


【解决方案1】:

鉴于您以无人看管的方式使用互操作,可能会发生各种奇怪/意外的事情。我承认,我不知道您为什么会在不同环境中遇到测试用例的症状。我有一种非常强烈的感觉,无人看管是罪魁祸首。互操作在用户的登录上下文中运行,如果没有用户……嗯……是的。那么,如何解决这个问题并且仍然无人看管呢?首先想到的是使用 OpenXML SDK。这是以无人看管的方式处理办公文件的安全方式。我自己用它来生成无人值守的报告。

假设:

  • 标准 DOCX 格式
  • 文档包含文字/图片/样式/任何内容。这不仅仅是一袋图像(如果是的话,还有更简单的方法可以完成您的需要)

API:

http://www.microsoft.com/en-us/download/details.aspx?id=30425

但是,您不能使用 OpenXML 将文档转换为图像!我想到了一种解决方法,但这未经测试。我们的想法是将 doc 转换为 html,然后渲染 html 并将其填充到图像中。

这是一种使用 OpenXML 将 Word 文档转换为 HTML 的方法:

可以做各种方便事情的大型电动工具: http://powertools.codeplex.com/

您需要的特定模块:http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2014/01/30/transform-docx-to-html-css-with-high-fidelity-using-powertools-for-open-xml.aspx

这是一个方便的库,用于渲染 HTML 并将其转储到图像中: http://htmlrenderer.codeplex.com/

【讨论】:

  • 这有点矫枉过正,因为我真正需要做的就是提高图像分辨率并从整体中获得可行的图像,将 MemoryStream 转换为字节数组,然后转换为位图,从我可以根据需要调整它的大小。问题是,当您以 100% 缩放打开文档时,它已经非常小了,因此从某种意义上说,代码正在按预期工作。我只是感到困惑,登录给我的视野要好得多(2023x1279 与 200x120 之类的东西)。尽管如此,我会给你一个写得好的回复投赞成票:) 即使这不是我所追求的。
  • 谢谢!我同意它的矫枉过正,但我​​在无人值守的 Windows 服务中使用互操作时遇到了很多地雷,我非常害怕它。
【解决方案2】:
using (var ms = new MemoryStream((byte[])(bits)))
        {
            var emf = new Metafile(ms);
            var scale = 400 / emf.HorizontalResolution;
            var Width= emf.Width * scale;
            var Height = emf.Height * scale;
            System.Drawing.Bitmap b = new System.Drawing.Bitmap((Int32)Width, (Int32)Height);
            var G = System.Drawing.Graphics.FromImage(b);
            G.Clear(System.Drawing.Color.White);
            G.DrawImage(emf, 0, 0, (float)Width, (float)Height);
            b.Save(pngTarget, System.Drawing.Imaging.ImageFormat.Png);
        }

【讨论】:

  • 请避免仅使用代码的答案。更新您的帖子,用简单的语言阐述您的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
  • 2011-02-01
  • 2020-06-15
  • 2012-06-01
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多