Hi,
I've searched the
entire internet for two consecutive days, with little to no success on this issue:
To
append images in the
System.Windows.Forms.RichTextBox class without copying to clipboard or any other
dirty tricks, I have stumbled upon the
ExRichTextBox class by Khendys Gordon here on
http://www.codeproject.com
This class can convert an
Image type to the corresponding
RTF string which is needed to display it in the RichTextBox.
The RTF's picture control
MUST be
.WMF data either in binary or hexadecimals (this is also what WordPad does when you insert an image). WordPad and the RichTextBox ignores every other control word (e.g. PNG, JPG etc.) for pictures in RTF.
See page 148 in the RTF Specification
Now here is the problem:
http://puu.sh/1XnKL.jpg (image was 19x25 so I zoomed a little bit)
- The left one is converted from PNG to WMF using ExRichTextBox
- The right one is directly added to WordPad (so WordPad did the conversion)
Now, in the ExRichTextBox class the conversion goes by the following:
1. Create
EMF from the Bitmap/Image,
2. then convert to WMF by using unmanaged code functions (in
GDI+ API)
3. finally convert the bytes to hexadecimals
Here is the code of the method which returns the WMF data when you pass an Image type. This method is in the ExRichTextBox class which inherits from System.Windows.Forms.RichTextBox:
[DllImportAttribute("gdiplus.dll")]
private static extern uint GdipEmfToWmfBits (IntPtr _hEmf, uint _bufferSize,
byte[] _buffer, int _mappingMode, EmfToWmfBitsFlags _flags);
private string GetRtfImage(Image _image) {
StringBuilder _rtf = null;
MemoryStream _stream = null;
Graphics _graphics = null;
Metafile _metaFile = null;
IntPtr _hdc;
try {
_rtf = new StringBuilder();
_stream = new MemoryStream();
using(_graphics = this.CreateGraphics()) {
_hdc = _graphics.GetHdc();
_metaFile = new Metafile(_stream, _hdc);
_graphics.ReleaseHdc(_hdc);
}
using(_graphics = Graphics.FromImage(_metaFile)) {
_graphics.DrawImage(_image, new Rectangle(0, 0, _image.Width,
_image.Height));
}
IntPtr _hEmf = _metaFile.GetHenhmetafile();
uint _bufferSize = GdipEmfToWmfBits(_hEmf, 0, null, MM_ANISOTROPIC,
EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
byte[] _buffer = new byte[_bufferSize];
uint _convertedSize = GdipEmfToWmfBits(_hEmf, _bufferSize, _buffer,
MM_ANISOTROPIC, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
for(int i = 0; i < _buffer.Length; ++i) {
_rtf.Append(String.Format("{0:X2}", _buffer[i]));
}
return _rtf.ToString();
}
finally {
if(_graphics != null)
_graphics.Dispose();
if(_metaFile != null)
_metaFile.Dispose();
if(_stream != null)
_stream.Close();
}
}
Question: WHY and WHERE does the image lose its quality?