22 c# rtf image image-formats
我正在尝试将图像添加到我正在创建的RTF文档中.我宁愿不使用"复制/粘贴"的方法(即涉及粘贴一个RichTextBox内的图像,然后访问.RTF属性),它清除剪贴板(因为这将是我的最终用户的麻烦和混乱).
到目前为止我的代码返回了需要插入RTF文档以打印图像的字符串.输入的图像(位于$ path)通常采用bmp或jpeg格式,但在这个阶段我并不关心图像是如何存储在RTF中的,只是我可以让它工作.
public string GetImage(string path, int width, int height)
{
MemoryStream stream = new MemoryStream();
string newPath = Path.Combine(Environment.CurrentDirectory, path);
Image img = Image.FromFile(newPath);
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
byte [] bytes = stream.ToArray();
string str = BitConverter.ToString(bytes, 0).Replace("-", string.Empty);
//string str = System.Text.Encoding.UTF8.GetString(bytes);
string mpic = @"{\pict\pngblip\picw" +
img.Width.ToString() + @"\pich" + img.Height.ToString() +
@"\picwgoa" + width.ToString() + @"\pichgoa" + height.ToString() +
@"\hex " + str + "}";
return mpic
}
Run Code Online (Sandbox Code Playgroud)
但问题是这段代码不起作用,因为据我所知,字符串str没有正确的字符串转换在RTF中工作.
编辑:我的问题是在@"\ hex"中的\ hex之后缺少一个空格,并且也没有从BitConverter的返回值中删除" - "字符
RRU*_*RUZ 28
试试这些链接
你必须将"picwgoa"改为"picwgoal",将"pichgoa"改为"pichgoal"
string mpic = @"{\pict\pngblip\picw" +
img.Width.ToString() + @"\pich" + img.Height.ToString() +
@"\picwgoal" + width.ToString() + @"\pichgoal" + height.ToString() +
@"\bin " + str + "}";
Run Code Online (Sandbox Code Playgroud)
在这里,您有一个支持的图像格式列表
\emfblip Source of the picture is an EMF (enhanced metafile).
\pngblip Source of the picture is a PNG.
\jpegblip Source of the picture is a JPEG.
\shppict Specifies a Word 97-2000 picture. This is a destination control word.
\nonshppict Specifies that Word 97-2000 has written a {\pict destination that it will not read on input. This keyword is for compatibility with other readers.
\macpict Source of the picture is QuickDraw.
\pmmetafileN Source of the picture is an OS/2 metafile. The N argument identifies the metafile type. The N values are described in the \pmmetafile table below.
\wmetafileN Source of the picture is a Windows metafile. The N argument identifies the metafile type (the default is 1).
\dibitmapN Source of the picture is a Windows device-independent bitmap. The N argument identifies the bitmap type (must equal 0).The information to be included in RTF from a Windows device-independent bitmap is the concatenation of the BITMAPINFO structure followed by the actual pixel data.
\wbitmapN Source of the picture is a Windows device-dependent bitmap. The N argument identifies the bitmap type (must equal 0).The information to be included in RTF from a Windows device-dependent bitmap is the result of the GetBitmapBits function.
小智 12
花了一天左右的谷歌搜索答案.拼凑来自遍布stackoverflow和其他来源的花絮.输入此图像,它将返回您需要添加到richtextbox.rtf扩展名的字符串.图像宽度变化并需要计算,给出公式.
// RTF Image Format
// {\pict\wmetafile8\picw[A]\pich[B]\picwgoal[C]\pichgoal[D]
//
// A = (Image Width in Pixels / Graphics.DpiX) * 2540
//
// B = (Image Height in Pixels / Graphics.DpiX) * 2540
//
// C = (Image Width in Pixels / Graphics.DpiX) * 1440
//
// D = (Image Height in Pixels / Graphics.DpiX) * 1440
[Flags]
enum EmfToWmfBitsFlags
{
EmfToWmfBitsFlagsDefault = 0x00000000,
EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
EmfToWmfBitsFlagsNoXORClip = 0x00000004
}
const int MM_ISOTROPIC = 7;
const int MM_ANISOTROPIC = 8;
[DllImport("gdiplus.dll")]
private static extern uint GdipEmfToWmfBits(IntPtr _hEmf, uint _bufferSize,
byte[] _buffer, int _mappingMode, EmfToWmfBitsFlags _flags);
[DllImport("gdi32.dll")]
private static extern IntPtr SetMetaFileBitsEx(uint _bufferSize,
byte[] _buffer);
[DllImport("gdi32.dll")]
private static extern IntPtr CopyMetaFile(IntPtr hWmf,
string filename);
[DllImport("gdi32.dll")]
private static extern bool DeleteMetaFile(IntPtr hWmf);
[DllImport("gdi32.dll")]
private static extern bool DeleteEnhMetaFile(IntPtr hEmf);
public static string GetEmbedImageString(Bitmap image)
{
Metafile metafile = null;
float dpiX; float dpiY;
using (Graphics g = Graphics.FromImage (image))
{
IntPtr hDC = g.GetHdc ();
metafile = new Metafile (hDC, EmfType.EmfOnly);
g.ReleaseHdc (hDC);
}
using (Graphics g = Graphics.FromImage (metafile))
{
g.DrawImage (image, 0, 0);
dpiX = g.DpiX;
dpiY = g.DpiY;
}
IntPtr _hEmf = metafile.GetHenhmetafile ();
uint _bufferSize = GdipEmfToWmfBits (_hEmf, 0, null, MM_ANISOTROPIC,
EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
byte[] _buffer = new byte[_bufferSize];
GdipEmfToWmfBits (_hEmf, _bufferSize, _buffer, MM_ANISOTROPIC,
EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
IntPtr hmf = SetMetaFileBitsEx (_bufferSize, _buffer);
string tempfile = Path.GetTempFileName ();
CopyMetaFile (hmf, tempfile);
DeleteMetaFile (hmf);
DeleteEnhMetaFile (_hEmf);
var stream = new MemoryStream ();
byte[] data = File.ReadAllBytes (tempfile);
//File.Delete (tempfile);
int count = data.Length;
stream.Write (data, 0, count);
string proto = @"{\rtf1{\pict\wmetafile8\picw" + (int)( ( (float)image.Width / dpiX ) * 2540 )
+ @"\pich" + (int)( ( (float)image.Height / dpiY ) * 2540 )
+ @"\picwgoal" + (int)( ( (float)image.Width / dpiX ) * 1440 )
+ @"\pichgoal" + (int)( ( (float)image.Height / dpiY ) * 1440 )
+ " "
+ BitConverter.ToString(stream.ToArray()).Replace("-", "")
+ "}}";
return proto;
}
Run Code Online (Sandbox Code Playgroud)
此页面的后来访问者(例如我几天前)可能会发现以下链接很有用:使用 .NET 将图像转换为 WMF
人们会发现写字板会忽略任何未以正确的 Windows 图元文件格式存储的图像。因此,本页上的前面的示例根本不会显示(尽管它在 OpenOffice 和 Word 本身中工作得很好)。写字板支持的格式是:
{/pict/wmetafile8/picw[width]/pich[height]/picwgoal[scaledwidth]/pichgoal[scaledheight] [image-as-string-of-byte-hex-values]} (方括号中的术语替换为适当的数据)。
可以按照上述链接中的步骤来获取“适当的数据”。对于那些使用 python 寻找解决方案的人来说,这是一个解决方案的开始(我相信仍然存在一些 dpi/缩放问题)。这需要PIL(或Pillow)、ctypes和clr (Python .NET)。首先使用 PIL/Pillow 打开图像。在这里我将其打开为“canv”:
from ctypes import *
import clr
clr.AddReference("System.IO")
clr.AddReference("System.Drawing")
from System import IntPtr
from System.Drawing import SolidBrush
from System.Drawing import Color
from System.Drawing import Imaging
from System.Drawing import Graphics
from System.IO import FileStream
from System.IO import FileMode
from System.IO import MemoryStream
from System.IO import File
def byte_to_hex(bytefile):
acc = ''
b = bytefile.read(1)
while b:
acc+=("%02X" % ord(b))
b = bytefile.read(1)
return acc.strip()
#... in here is some code where 'canv' is created as the PIL image object, and
#... 'template' is defined as a string with placeholders for picw, pich,
#... picwgoal, pichgoal, and the image data
mfstream = MemoryStream()
offscrDC = Graphics.FromHwndInternal(IntPtr.Zero)
imgptr = offscrDC.GetHdc()
mfile = Imaging.Metafile(mfstream, imgptr, Imaging.EmfType.EmfOnly)
gfx = Graphics.FromImage(mfile)
width,height = canv.size
pixels = canv.load()
for x in range(width):
for y in range(height):
_r,_g,_b = pixels[x, y]
c = Color.FromArgb(_r, _g, _b)
brush = SolidBrush(c)
gfx.FillRectangle(brush, x, y, 1, 1)
gfx.Dispose()
offscrDC.ReleaseHdc()
_hEmf = mfile.GetHenhmetafile()
GdipEmfToWmfBits = windll.gdiplus.GdipEmfToWmfBits
_bufferSize = GdipEmfToWmfBits(
int(str(_hEmf)),
c_uint(0),
None,
c_int(8), # MM_ANISOTROPIC
c_uint(0x00000000)) # Default flags
_buffer = c_int * _bufferSize
_buffer = _buffer(*[0 for x in range(_bufferSize)])
GdipEmfToWmfBits( int(str(_hEmf)),
c_uint(_bufferSize),
_buffer,
c_int(8), # MM_ANISOTROPIC
c_uint(0x00000000) ) # Default flags
hmf = windll.gdi32.SetMetaFileBitsEx(c_uint(_bufferSize), _buffer)
windll.gdi32.CopyMetaFileA(int(str(hmf)), "temp.wmf")
windll.gdi32.DeleteMetaFile(int(str(hmf)))
windll.gdi32.DeleteEnhMetaFile(int(str(_hEmf)))
mfstream.Close()
imgstr = open("temp.wmf", 'rb')
imgstr = byte_to_hex(imgstr)
with open('script-out.rtf','wb') as outf:
template = template % (str(_cx),str(_cy),str(15*_cx),str(15*_cy),imgstr)
outf.write(template)
Run Code Online (Sandbox Code Playgroud)