[C#] RTF文本到位图图像?有什么简单的方法吗? [英] [C#] RTF text to bitmap image? Any easy way around?

查看:178
本文介绍了[C#] RTF文本到位图图像?有什么简单的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我正在研究一个大声笑"项目,该项目应该像半简单的图像编辑器一样工作,我目前正在寻找一种向图像添加文本的方法.文本是如何进行RTF编码的(以获取粗体/斜体等选项),我真的想将其添加到程序中.

我已经看到了一些"hacks",但是它们绝对不容易使用,如果可能的话,我宁愿遵循"KISS模型"(Keep It Simple Stupid).

基本上发生的是,您可以在图像上添加文本,其中我弹出了一些最需要的东西(粗体/斜体,字体类型等),但是我已经寻找了几个小时,以找到一种转换方法图片上只有文字(不是整个RTF框),但是没有运气...我看过这样的东西:

http://www.sitepoint.com/forums/showthread.php?676093-Font- Metrics-C [ ^ ]
http://msdn.microsoft.com/zh-CN/library/xwf9s90b (v = vs.80).aspx [ http://help.syncfusion.com/UG/Reporting/pdf /WPF/default.htm#!documents/41211drawingtext.htm [

Hi im working on a little "lol" project that should work like a semi-simple image editor, and i am currently looking for a way to add text to a image. How ever the text is RTF encoded (to get the bold/italic etc. options) and i really wanna have this added to the program.

I''ve seen a few "hacks" to get around but they''re absolutely not easy to use, and i would prefer to follow the "KISS Model" (Keep It Simple Stupid) if possible.

What basically happens is you can add a text to the image where i''ve made a little popup with the most necessary things needed (Bold/italic, font types ets.) but i have seached for hours now to find a way to convert the text ONLY (not whole RTF box) onto the picture but no luck... i''ve looked at stuff like this:

http://www.sitepoint.com/forums/showthread.php?676093-Font-Metrics-C[^]
http://msdn.microsoft.com/en-US/library/xwf9s90b(v=vs.80).aspx[^]
http://help.syncfusion.com/UG/Reporting/pdf/WPF/default.htm#!documents/41211drawingtext.htm[^]

and many options such as System.Windows.Forms.Control.DrawToBitmap(System.Drawing.Bitmap, System.Drawing.Rectangle) (sadly i get find this one/make it work)

none of above have worked as planned so i hope some in here may be able to help me.

Thanks A LOT in advance.

HTML Encoding may be a option too if that is easier.

推荐答案

我发现此类最近扩展了图形类,我对其进行了一些更改,并且它确实我所要求的一切!

I found this class recent extending the graphics class, i changed it a little, and it does everything i could ask for!

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Text;

public static class Graphics_DrawRtfText 
{
    private static RichTextBoxDrawer rtfDrawer;
    public static void DrawRtfText(this Graphics graphics, string rtf, RectangleF layoutArea,float xFactor) 
    {
        if (Graphics_DrawRtfText.rtfDrawer == null) 
        {
            Graphics_DrawRtfText.rtfDrawer = new RichTextBoxDrawer();
        }
        Graphics_DrawRtfText.rtfDrawer.Rtf = rtf;
        Graphics_DrawRtfText.rtfDrawer.Draw(graphics, layoutArea,xFactor);
    }

    private class RichTextBoxDrawer : RichTextBox 
    {
        //Code converted from code found here: http://support.microsoft.com/kb/812425/en-us

        //Convert the unit used by the .NET framework (1/100 inch) 
        //and the unit used by Win32 API calls (twips 1/1440 inch)
        private const double anInch = 14.4;

        public void LineSpace()
        {
            SafeNativeMethods.PARAFORMAT2 fmt = new SafeNativeMethods.PARAFORMAT2();
            fmt.cbSize = Marshal.SizeOf(fmt);
            fmt.dwMask |= SafeNativeMethods.PFM_LINESPACING | SafeNativeMethods.PFM_SPACEAFTER;

            fmt.dyLineSpacing = (int)(22 * this.SelectionFont.SizeInPoints); // in twips
            // specify exact line spacing
            fmt.bLineSpacingRule = Convert.ToByte(4);
            SafeNativeMethods.SendMessage(this.Handle, SafeNativeMethods.EM_SETPARAFORMAT, 0, ref fmt); // 0 - to all text. 1 - only to seleted
        }

        public void LineSpace(int _linespace)
        {
            SafeNativeMethods.PARAFORMAT2 fmt = new SafeNativeMethods.PARAFORMAT2();
            fmt.cbSize = Marshal.SizeOf(fmt);
            fmt.dwMask |= SafeNativeMethods.PFM_LINESPACING | SafeNativeMethods.PFM_SPACEAFTER;

            fmt.dyLineSpacing = _linespace; // in twips
            // specify exact line spacing
            fmt.bLineSpacingRule = Convert.ToByte(4);
            SafeNativeMethods.SendMessage(this.Handle, SafeNativeMethods.EM_SETPARAFORMAT, 0, ref fmt); // 0 - to all text. 1 - only to seleted
        }

        protected override CreateParams CreateParams 
        {
            get 
            {
                CreateParams createParams = base.CreateParams;
                if (SafeNativeMethods.LoadLibrary("msftedit.dll") != IntPtr.Zero) 
                {
                    createParams.ExStyle |= SafeNativeMethods.WS_EX_TRANSPARENT; // transparent
                    createParams.ClassName = "RICHEDIT50W";
                }
                return createParams;
            }
        }

        private void DPToHIMETRIC(Graphics graphics,ref SizeF size)
        {
            size.Width = (size.Width * 2540.0f) / graphics.DpiX;
            size.Height = (size.Height * 2540.0f) / graphics.DpiY;
        }

        public void Draw(Graphics graphics, RectangleF layoutArea, float xFactor) 
        {
            System.Diagnostics.Debug.WriteLine("LayoutArea " + layoutArea);
            
            SizeF metaSize = layoutArea.Size;
            DPToHIMETRIC(graphics, ref metaSize);

            System.Diagnostics.Debug.WriteLine("MetaSize " + metaSize);

            IntPtr hdc = graphics.GetHdc();

            //create a metafile, convert the size to himetrics
            Metafile metafile = new Metafile(hdc, new RectangleF(0,0,metaSize.Width,metaSize.Height));

            graphics.ReleaseHdc(hdc);

            Graphics g = Graphics.FromImage(metafile);
            IntPtr hDCEMF = g.GetHdc();

            //Calculate the area to render.
            SafeNativeMethods.RECT rectLayoutArea;
            rectLayoutArea.Left = 0;
            rectLayoutArea.Top = 0;
            rectLayoutArea.Right = (int)((1440 * metaSize.Width + 2540 / 2) / 2540);
            rectLayoutArea.Bottom = (int)((1440 * metaSize.Height + 2540 / 2) / 2540);

            System.Diagnostics.Debug.WriteLine(String.Format("RectLayoutArea ({0},{1})",rectLayoutArea.Right,rectLayoutArea.Bottom));

            SafeNativeMethods.FORMATRANGE fmtRange;
            fmtRange.chrg.cpMax = -1;            //Indicate character from to character to 
            fmtRange.chrg.cpMin = 0;
            fmtRange.hdc = hDCEMF;                  //Use the same DC for measuring and rendering
            fmtRange.hdcTarget = hDCEMF;         //Point at printer hDC
            fmtRange.rc = rectLayoutArea;        //Indicate the area on page to print
            fmtRange.rcPage = rectLayoutArea;    //Indicate size of page

            IntPtr wParam = IntPtr.Zero;
            wParam = new IntPtr(1);

            //Get the pointer to the FORMATRANGE structure in memory
            IntPtr lParam = IntPtr.Zero;
            lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
            Marshal.StructureToPtr(fmtRange, lParam, false);

            SafeNativeMethods.SendMessage(this.Handle, SafeNativeMethods.EM_FORMATRANGE, wParam, lParam);
            SafeNativeMethods.SendMessage(this.Handle, SafeNativeMethods.EM_FORMATRANGE, wParam, IntPtr.Zero);

            //Free the block of memory allocated
            Marshal.FreeCoTaskMem(lParam);

            //Release the device context handle obtained by a previous call
            g.ReleaseHdc(hDCEMF);
            g.Dispose();

            hdc = graphics.GetHdc();
            int nHorzSize = SafeNativeMethods.GetDeviceCaps(hdc, SafeNativeMethods.DeviceCap.HORZSIZE);
            int nVertSize = SafeNativeMethods.GetDeviceCaps(hdc, SafeNativeMethods.DeviceCap.VERTSIZE);
            int nHorzRes = SafeNativeMethods.GetDeviceCaps(hdc, SafeNativeMethods.DeviceCap.HORZRES);
            int nVertRes = SafeNativeMethods.GetDeviceCaps(hdc, SafeNativeMethods.DeviceCap.VERTRES);
            int nLogPixelsX = SafeNativeMethods.GetDeviceCaps(hdc, SafeNativeMethods.DeviceCap.LOGPIXELSX);
            int nLogPixelsY = SafeNativeMethods.GetDeviceCaps(hdc, SafeNativeMethods.DeviceCap.LOGPIXELSY);
            graphics.ReleaseHdc(hdc);

            float fHorzSizeInches = nHorzSize / 25.4f;
            float fVertSizeInches = nVertSize / 25.4f;
            float fHorzFudgeFactor = (nHorzRes / fHorzSizeInches) / nLogPixelsX;
            float fVertFudgeFactor = (nVertRes / fVertSizeInches) / nLogPixelsY;

            System.Diagnostics.Debug.WriteLine("Fudge Factor " + fHorzFudgeFactor.ToString() + " " + fVertFudgeFactor.ToString() + " XFactor " + xFactor.ToString());

            Pen RedPen = new Pen(Color.Red);
            graphics.DrawRectangle(RedPen, layoutArea.X * xFactor, layoutArea.Y * xFactor, layoutArea.Width * xFactor, layoutArea.Height * xFactor);

            float Left = layoutArea.Left;
            float Top = layoutArea.Top;
            //layoutArea.X = layoutArea.Y = 0;
            layoutArea.Offset(-Left, -Top);
            layoutArea.Offset(Left / fHorzFudgeFactor, Top / fVertFudgeFactor);

            System.Drawing.Drawing2D.GraphicsState state = graphics.Save();
            graphics.ScaleTransform(fHorzFudgeFactor * xFactor, fVertFudgeFactor * xFactor);
            graphics.DrawImage(metafile, layoutArea);
            graphics.Restore(state);


            System.Diagnostics.Debug.WriteLine("Layout Aread : "+layoutArea);
       }

        #region SafeNativeMethods
        private static class SafeNativeMethods 
        {
            [DllImport("USER32.dll")]
            public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

            [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr LoadLibrary(string lpFileName);
            
            [DllImport("gdi32.dll")]
            public static extern int GetDeviceCaps(IntPtr hdc, DeviceCap nIndex);

            [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
            public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref PARAFORMAT2 lParam);

            [StructLayout(LayoutKind.Sequential)]
            public struct RECT 
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct CHARRANGE 
            {
                public int cpMin;        //First character of range (0 for start of doc)
                public int cpMax;        //Last character of range (-1 for end of doc)
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct FORMATRANGE 
            {
                public IntPtr hdc;                //Actual DC to draw on
                public IntPtr hdcTarget;    //Target DC for determining text formatting
                public RECT rc;                        //Region of the DC to draw to (in twips)
                public RECT rcPage;                //Region of the whole DC (page size) (in twips)
                public CHARRANGE chrg;        //Range of text to draw (see earlier declaration)
            }

            public enum DeviceCap : int
            {
                /// <summary>
                /// Device driver version
                /// </summary>
                DRIVERVERSION = 0,
                /// <summary>
                /// Device classification
                /// </summary>
                TECHNOLOGY = 2,
                /// <summary>
                /// Horizontal size in millimeters
                /// </summary>
                HORZSIZE = 4,
                /// <summary>
                /// Vertical size in millimeters
                /// </summary>
                VERTSIZE = 6,
                /// <summary>
                /// Horizontal width in pixels
                /// </summary>
                HORZRES = 8,
                /// <summary>
                /// Vertical height in pixels
                /// </summary>
                VERTRES = 10,
                /// <summary>
                /// Number of bits per pixel
                /// </summary>
                BITSPIXEL = 12,
                /// <summary>
                /// Number of planes
                /// </summary>
                PLANES = 14,
                /// <summary>
                /// Number of brushes the device has
                /// </summary>
                NUMBRUSHES = 16,
                /// <summary>
                /// Number of pens the device has
                /// </summary>
                NUMPENS = 18,
                /// <summary>
                /// Number of markers the device has
                /// </summary>
                NUMMARKERS = 20,
                /// <summary>
                /// Number of fonts the device has
                /// </summary>
                NUMFONTS = 22,
                /// <summary>
                /// Number of colors the device supports
                /// </summary>
                NUMCOLORS = 24,
                /// <summary>
                /// Size required for device descriptor
                /// </summary>
                PDEVICESIZE = 26,
                /// <summary>
                /// Curve capabilities
                /// </summary>
                CURVECAPS = 28,
                /// <summary>
                /// Line capabilities
                /// </summary>
                LINECAPS = 30,
                /// <summary>
                /// Polygonal capabilities
                /// </summary>
                POLYGONALCAPS = 32,
                /// <summary>
                /// Text capabilities
                /// </summary>
                TEXTCAPS = 34,
                /// <summary>
                /// Clipping capabilities
                /// </summary>
                CLIPCAPS = 36,
                /// <summary>
                /// Bitblt capabilities
                /// </summary>
                RASTERCAPS = 38,
                /// <summary>
                /// Length of the X leg
                /// </summary>
                ASPECTX = 40,
                /// <summary>
                /// Length of the Y leg
                /// </summary>
                ASPECTY = 42,
                /// <summary>
                /// Length of the hypotenuse
                /// </summary>
                ASPECTXY = 44,
                /// <summary>
                /// Shading and Blending caps
                /// </summary>
                SHADEBLENDCAPS = 45,

                /// <summary>
                /// Logical pixels inch in X
                /// </summary>
                LOGPIXELSX = 88,
                /// <summary>
                /// Logical pixels inch in Y
                /// </summary>
                LOGPIXELSY = 90,

                /// <summary>
                /// Number of entries in physical palette
                /// </summary>
                SIZEPALETTE = 104,
                /// <summary>
                /// Number of reserved entries in palette
                /// </summary>
                NUMRESERVED = 106,
                /// <summary>
                /// Actual color resolution
                /// </summary>
                COLORRES = 108,

                // Printing related DeviceCaps. These replace the appropriate Escapes
                /// <summary>
                /// Physical Width in device units
                /// </summary>
                PHYSICALWIDTH = 110,
                /// <summary>
                /// Physical Height in device units
                /// </summary>
                PHYSICALHEIGHT = 111,
                /// <summary>
                /// Physical Printable Area x margin
                /// </summary>
                PHYSICALOFFSETX = 112,
                /// <summary>
                /// Physical Printable Area y margin
                /// </summary>
                PHYSICALOFFSETY = 113,
                /// <summary>
                /// Scaling factor x
                /// </summary>
                SCALINGFACTORX = 114,
                /// <summary>
                /// Scaling factor y
                /// </summary>
                SCALINGFACTORY = 115,

                /// <summary>
                /// Current vertical refresh rate of the display device (for displays only) in Hz
                /// </summary>
                VREFRESH = 116,
                /// <summary>
                /// Horizontal width of entire desktop in pixels
                /// </summary>
                DESKTOPVERTRES = 117,
                /// <summary>
                /// Vertical height of entire desktop in pixels
                /// </summary>
                DESKTOPHORZRES = 118,
                /// <summary>
                /// Preferred blt alignment
                /// </summary>
                BLTALIGNMENT = 119
            }

            public struct PARAFORMAT2
            {

                public int cbSize;

                public uint dwMask;

                public short wNumbering;

                public short wReserved;

                public int dxStartIndent;

                public int dxRightIndent;

                public int dxOffset;

                public short wAlignment;

                public short cTabCount;

                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]

                public int[] rgxTabs;

                // PARAFORMAT2 from here onwards.

                public int dySpaceBefore;

                public int dySpaceAfter;

                public int dyLineSpacing;

                public short sStyle;

                public byte bLineSpacingRule;

                public byte bOutlineLevel;

                public short wShadingWeight;

                public short wShadingStyle;

                public short wNumberingStart;

                public short wNumberingStyle;

                public short wNumberingTab;

                public short wBorderSpace;

                public short wBorderWidth;

                public short wBorders;

            }

            public const int EM_FORMATRANGE = WM_USER + 57;

            public const int PFM_SPACEAFTER = 128;

            public const int PFM_LINESPACING = 256;

            public const int EM_SETPARAFORMAT = 1095;

            public const int WM_USER = 0x0400;

            public const int WS_EX_TRANSPARENT = 0x20;

        }
        #endregion
    }
}


You need the Graphics.DrawString method. You can get the Graphics object by Graphics.FromImage. And then draw all the text your self...
You need the Graphics.DrawString method. You can get the Graphics object by Graphics.FromImage. And then draw all the text your self...


There are two options here:

There are two options here:


  • You can write the text to a RichTextBox and then screen capture it with Control.DrawToBitmap[^]. You probably need to post-process the Bitmap you get to sort out the transparency.
  • You can write a miniature RTF (or HTML or other tagging system; RTF is pretty disgusting to type) interpreter to break the text up into sections, and then use Graphics.DrawString and Graphics.MeasureCharacterRanges to write the text onto your target image.


这篇关于[C#] RTF文本到位图图像?有什么简单的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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