Created
March 1, 2010 18:01
-
-
Save mccoder/318611 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h1> | |
<a href="http://www.gotdotnet.ru/blogs/alexeylyubko/7205/" >Рендеринг HTML в Bitmap</a> | |
</h1> | |
<strong>Автор</strong>: Sveer<br/> | |
<strong>Дата публикации</strong>: 28.2.2010 16:07<br/> | |
<strong>Categories</strong>: howto, htmltobitmap, html rendering<br/> | |
<br/>В процессе рефакторинга проекта <noindex> | |
<a rel="nofollow" href="http://qrpr.ru/" >QRPR</a> | |
</noindex> накопал много небольших, но полезных вспомогательных блоков. Решил начать ими делиться и возобновить блог :) <p>Ищите под тегом HOWTO :)</p> <p> | |
<strong>Задача:</strong> <br/> | |
</p> <p>Есть HTML, который может содержать и картинки и текст и разлисное форматирование. необходимо получить его представление в виде Картинки (Bitmap).</p> <p> | |
<strong>Решение:</strong> | |
</p> <p>Для этих целей есть несколько способов:</p> <p>1 - использовать Движок <noindex> | |
<a rel="nofollow" href="http://webkit.org/" >WebKit</a> | |
</noindex>, собрать его, воспользоваться оберткой <noindex> | |
<a rel="nofollow" href="http://webkitdotnet.sourceforge.net/" >WebKit для .NET</a> | |
</noindex>. На этом мы остановились, замерив время подгрузки WebKit в наше ASP.NET приложение.</p> <p>2 - использовать COM-компонент WebBrowser. </p> <p>Базовое описание такого решения есть на <noindex> | |
<a rel="nofollow" href="http://www.codeproject.com/KB/graphics/IECapture.aspx" >CodeProject</a> | |
</noindex>, но нам оно не подошло, т.к. нужна была отдельная библиотека и возможность использования в ASP.NET</p> <p>Это решение я и опишу.</p> <p>Шаги по использованию очень просты:</p> <ul> | |
<li>Создаем объект WebBrowser</li> | |
<li>Загружаем в него HTML</li> | |
<li>Ждем окончания рендеринга</li> | |
<li>Изменяем размер компонента под наши нужды (в нашем случае необхоидмо чтобы строки не переносились без <BR></li> | |
<li>Ждем окончания рендеринга</li> | |
<li>Сохраняем содержимое окна компонента с помощью интерфейса IHTMLElementRender2</li> | |
</ul> | |
<p>При этом важно понимать, в каком потоке будет использоваться этот компонент, т.к. WebBrowser должен работать в потоке STA!</p> <p>Необходимо подключить компонент mshtml, чтобы мы могли использовать интерфейсы </p> <p>Затем объявляем интерфейс, которй будем использовать для рендеринга</p> <p/> | |
<div class="blog-code-box" > | |
<pre class="csharp" >[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |
[Guid("3050F669-98B5-11CF-BB82-00AA00BDCE0B")] | |
public interface IHTMLElementRender2 | |
{ | |
void DrawToDC(IntPtr hdc); | |
void SetDocumentPrinter(string bstrPrinterName, ref _RemotableHandle hdc); | |
}</pre> | |
</div> <br/> | |
<p>Затем мы реализовали варианты выхова рендеринга. Вы можете явно указать, запустить ли его в отдельном потоке и ждать окончания или же текущий уже является STAThread и можно запускать рендеринг в нем.</p> <p/> | |
<div class="blog-code-box" > | |
<pre class="csharp" >public static Bitmap RenderHTML (string html, bool atSTAThread) | |
{ | |
RenderInfo ri = new RenderInfo() { Html = html, Result=null }; | |
if (!atSTAThread) //Запускаем в отдельном потоке | |
Renderer(ri); | |
else | |
{ | |
System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Renderer)); | |
th.SetApartmentState(System.Threading.ApartmentState.STA); | |
th.Start(ri); | |
//Ждем окончания | |
if (!th.Join(55000)) | |
{ LogWriter(ex, QRPRErrorLevel.ErrorM2); } | |
} | |
return ri.Result; | |
}</pre> | |
</div> <br/> | |
Подготовка к рендерингу идет в методе Renderer: <br/> | |
<p/> | |
<div class="blog-code-box" > | |
<pre class="csharp" >private static void Renderer(object obj) | |
{ | |
try | |
{ | |
RenderInfo ri = (RenderInfo)obj; | |
WebBrowser webBrowser = new WebBrowser(); | |
webBrowser.ScrollBarsEnabled = true; | |
webBrowser.DocumentText = "" + ri.Html + ""; | |
while (webBrowser.ReadyState != WebBrowserReadyState.Complete) | |
{ | |
Application.DoEvents(); | |
} | |
//Выставляем блииинный Web-броузер чтобы правильно отображать. | |
webBrowser.Size = new Size(webBrowser.Document.Body.ScrollRectangle.Width, webBrowser.Document.Body.ScrollRectangle.Height); | |
while (webBrowser.ReadyState != WebBrowserReadyState.Complete) | |
{ | |
Application.DoEvents(); | |
} | |
webBrowser.ScrollBarsEnabled = false; | |
Rectangle rec = webBrowser.Document.Body.ClientRectangle; | |
ri.Result = GetBitmap(webBrowser, rec.Size.Width, rec.Size.Height); | |
} | |
catch(Exception ex) { | |
LogWriter(ex,QRPRErrorLevel.ErrorM2); | |
} | |
} | |
</pre> | |
</div> И сам рендеринг HTML! <p> | |
<br/> | |
</p> | |
<div class="blog-code-box" > | |
<pre class="csharp" >//Основной рендеринг HTML | |
private static Bitmap GetBitmap(WebBrowser webBrowser, int width, int height) | |
{ | |
IHTMLDocument2 rawDoc = (IHTMLDocument2)webBrowser.Document.DomDocument; | |
IHTMLElement rawBody = rawDoc.body; | |
IHTMLElementRender2 render = (IHTMLElementRender2)rawBody; | |
Bitmap bitmap = new Bitmap(width, height); | |
Rectangle bitmapRect = new Rectangle(0, 0, width, height); | |
webBrowser.DrawToBitmap(bitmap, bitmapRect); | |
using (Graphics graphics = Graphics.FromImage(bitmap)) | |
{ | |
IntPtr graphicshdc = graphics.GetHdc(); | |
render.DrawToDC(graphicshdc); | |
graphics.ReleaseHdc(graphicshdc); | |
#if DEBUG | |
//При отладке отрисовываем еще и прямоугольник | |
//graphics.DrawRectangle(Pens.Black, bitmapRect); | |
//graphics.Save(); | |
#endif | |
graphics.Dispose(); | |
return bitmap; | |
} | |
} | |
</pre> | |
</div> <p> | |
<br/> | |
Исходный код библиотеки можно <noindex> | |
<a rel="nofollow" href="http://it-arts.com/projects/renderhtmltobitmap.aspx" >скачать с it arts</a> | |
</noindex> | |
</p> <br/> | |
<br/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Рендеринг HTML в Bitmap] http://www.gotdotnet.ru/blogs/alexeylyubko/7205/ | |
Автор : Sveer | |
Дата публикации : 28.2.2010 16:07 | |
Categories : howto, htmltobitmap, html rendering | |
В процессе рефакторинга проекта | |
[QRPR] http://qrpr.ru/ | |
накопал много небольших, но полезных вспомогательных блоков. Решил начать ими делиться и возобновить блог :) | |
Ищите под тегом HOWTO :) | |
Задача: | |
Есть HTML, который может содержать и картинки и текст и разлисное форматирование. необходимо получить его представление в виде Картинки (Bitmap). | |
Решение: | |
Для этих целей есть несколько способов: | |
1 - использовать Движок | |
[WebKit] http://webkit.org/ | |
, собрать его, воспользоваться оберткой | |
[WebKit для .NET] http://webkitdotnet.sourceforge.net/ | |
. На этом мы остановились, замерив время подгрузки WebKit в наше ASP.NET приложение. | |
2 - использовать COM-компонент WebBrowser. | |
Базовое описание такого решения есть на | |
[CodeProject] http://www.codeproject.com/KB/graphics/IECapture.aspx | |
, но нам оно не подошло, т.к. нужна была отдельная библиотека и возможность использования в ASP.NET | |
Это решение я и опишу. | |
Шаги по использованию очень просты: | |
* Создаем объект WebBrowser | |
* Загружаем в него HTML | |
* Ждем окончания рендеринга | |
* Изменяем размер компонента под наши нужды (в нашем случае необхоидмо чтобы строки не переносились без <BR> | |
* Ждем окончания рендеринга | |
* Сохраняем содержимое окна компонента с помощью интерфейса IHTMLElementRender2 | |
При этом важно понимать, в каком потоке будет использоваться этот компонент, т.к. WebBrowser должен работать в потоке STA! | |
Необходимо подключить компонент mshtml, чтобы мы могли использовать интерфейсы | |
Затем объявляем интерфейс, которй будем использовать для рендеринга | |
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |
[Guid("3050F669-98B5-11CF-BB82-00AA00BDCE0B")] | |
public interface IHTMLElementRender2 | |
{ | |
void DrawToDC(IntPtr hdc); | |
void SetDocumentPrinter(string bstrPrinterName, ref _RemotableHandle hdc); | |
} | |
Затем мы реализовали варианты выхова рендеринга. Вы можете явно указать, запустить ли его в отдельном потоке и ждать окончания или же текущий уже является STAThread и можно запускать рендеринг в нем. | |
public static Bitmap RenderHTML (string html, bool atSTAThread) | |
{ | |
RenderInfo ri = new RenderInfo() { Html = html, Result=null }; | |
if (!atSTAThread) //Запускаем в отдельном потоке | |
Renderer(ri); | |
else | |
{ | |
System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Renderer)); | |
th.SetApartmentState(System.Threading.ApartmentState.STA); | |
th.Start(ri); | |
//Ждем окончания | |
if (!th.Join(55000)) | |
{ LogWriter(ex, QRPRErrorLevel.ErrorM2); } | |
} | |
return ri.Result; | |
} | |
Подготовка к рендерингу идет в методе Renderer: | |
private static void Renderer(object obj) | |
{ | |
try | |
{ | |
RenderInfo ri = (RenderInfo)obj; | |
WebBrowser webBrowser = new WebBrowser(); | |
webBrowser.ScrollBarsEnabled = true; | |
webBrowser.DocumentText = "" + ri.Html + ""; | |
while (webBrowser.ReadyState != WebBrowserReadyState.Complete) | |
{ | |
Application.DoEvents(); | |
} | |
//Выставляем блииинный Web-броузер чтобы правильно отображать. | |
webBrowser.Size = new Size(webBrowser.Document.Body.ScrollRectangle.Width, webBrowser.Document.Body.ScrollRectangle.Height); | |
while (webBrowser.ReadyState != WebBrowserReadyState.Complete) | |
{ | |
Application.DoEvents(); | |
} | |
webBrowser.ScrollBarsEnabled = false; | |
Rectangle rec = webBrowser.Document.Body.ClientRectangle; | |
ri.Result = GetBitmap(webBrowser, rec.Size.Width, rec.Size.Height); | |
} | |
catch(Exception ex) { | |
LogWriter(ex,QRPRErrorLevel.ErrorM2); | |
} | |
} | |
И сам рендеринг HTML! | |
//Основной рендеринг HTML | |
private static Bitmap GetBitmap(WebBrowser webBrowser, int width, int height) | |
{ | |
IHTMLDocument2 rawDoc = (IHTMLDocument2)webBrowser.Document.DomDocument; | |
IHTMLElement rawBody = rawDoc.body; | |
IHTMLElementRender2 render = (IHTMLElementRender2)rawBody; | |
Bitmap bitmap = new Bitmap(width, height); | |
Rectangle bitmapRect = new Rectangle(0, 0, width, height); | |
webBrowser.DrawToBitmap(bitmap, bitmapRect); | |
using (Graphics graphics = Graphics.FromImage(bitmap)) | |
{ | |
IntPtr graphicshdc = graphics.GetHdc(); | |
render.DrawToDC(graphicshdc); | |
graphics.ReleaseHdc(graphicshdc); | |
#if DEBUG | |
//При отладке отрисовываем еще и прямоугольник | |
//graphics.DrawRectangle(Pens.Black, bitmapRect); | |
//graphics.Save(); | |
#endif | |
graphics.Dispose(); | |
return bitmap; | |
} | |
} | |
Исходный код библиотеки можно | |
[скачать с it arts] http://it-arts.com/projects/renderhtmltobitmap.aspx |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment