Skip to content

Commit e2fd2d2

Browse files
authored
Merge pull request #10 from alfattack/auto-size-images
Automatically determine image height if one isn't provided
2 parents f107d80 + 6c9c962 commit e2fd2d2

File tree

2 files changed

+49
-50
lines changed

2 files changed

+49
-50
lines changed

Source/Demos/HtmlRenderer.Demo.Console/SkiaSvgConverter.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@ public SkiaSvgConverter(string sampleRunIdentifier, string basePath) : base(samp
1919
public async Task GenerateSampleAsync(HtmlSample sample)
2020
{
2121
var size = new SKSize(500, 1000);
22+
int width = 500;
23+
int height = 50;
2224

2325
using (var fileStream = File.Open(GetSamplePath(sample, ".svg"), FileMode.CreateNew))
2426
{
25-
await ImageGenerator.GenerateSvgAsync(sample.Html, fileStream, size, imageLoad: OnImageLoaded);
27+
await ImageGenerator.GenerateSvgAsync(sample.Html, fileStream, width, height, imageLoad: OnImageLoaded);
2628
fileStream.Flush();
2729
}
2830

2931
using (var fileStream = File.Open(GetSamplePath(sample, ".png"), FileMode.CreateNew))
3032
{
31-
await ImageGenerator.GenerateBitmapAsync(sample.Html, fileStream, size, SKEncodedImageFormat.Png, 100, imageLoad: OnImageLoaded);
33+
await ImageGenerator.GenerateBitmapAsync(sample.Html, fileStream, SKEncodedImageFormat.Png, width, imageLoad: OnImageLoaded);
3234
fileStream.Flush();
3335
}
3436
}

Source/HtmlRenderer.SkiaSharp/ImageGenerator.cs

Lines changed: 45 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -67,92 +67,89 @@ public static CssData ParseStyleSheet(string stylesheet, bool combineWithDefault
6767
/// <param name="stylesheetLoad">optional: can be used to overwrite stylesheet resolution logic</param>
6868
/// <param name="imageLoad">optional: can be used to overwrite image resolution logic</param>
6969
/// <returns>the generated image of the html</returns>
70-
public static async Task<SKCanvas> GenerateSvgAsync(
70+
public static async Task GenerateSvgAsync(
7171
string html,
7272
Stream outputStream,
73-
SKSize size,
73+
int width,
74+
int? height = null,
7475
CssData cssData = null,
7576
EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad = null,
7677
EventHandler<HtmlImageLoadEventArgs> imageLoad = null)
7778
{
78-
// create svg document to render the HTML into
79-
var canvas = SKSvgCanvas.Create(new SKRect(0, 0, size.Width, size.Height), outputStream);
80-
81-
// add rendered image
82-
await DrawSvgAsync(canvas, html, size, cssData, stylesheetLoad, imageLoad);
83-
canvas.Dispose();
84-
85-
return canvas;
79+
using (var container = await CreateHtmlContainer(html, width, cssData, stylesheetLoad, imageLoad))
80+
{
81+
var size = new SKSize(width, height ?? container.ActualSize.Height);
82+
var canvas = SKSvgCanvas.Create(new SKRect(0, 0, width, height ?? container.ActualSize.Height), outputStream);
83+
await DrawHtmlToCanvas(container, canvas);
84+
canvas.Dispose();
85+
}
8686
}
8787

8888
/// <summary>
8989
/// Writes html to a bitmap image
9090
/// </summary>
9191
/// <param name="html">HTML source to create image from</param>
92-
/// <param name="size">The size of the image</param>
9392
/// <param name="imageFormat">The file format used to encode the image.</param>
9493
/// <param name="quality">The quality level to use for the image. Quality range from 0-100. Higher values correspond to improved visual quality, but less compression.</param>
9594
/// <param name="cssData">optional: the style to use for html rendering (default - use W3 default style)</param>
9695
/// <param name="stylesheetLoad">optional: can be used to overwrite stylesheet resolution logic</param>
9796
/// <param name="imageLoad">optional: can be used to overwrite image resolution logic</param>
9897
/// <returns></returns>
99-
public static async Task<SKCanvas> GenerateBitmapAsync(
98+
public static async Task GenerateBitmapAsync(
10099
string html,
101100
Stream outputStream,
102-
SKSize size,
103101
SKEncodedImageFormat imageFormat,
104-
int quality,
102+
int width,
103+
int? height = null,
104+
int quality = 100,
105105
CssData cssData = null,
106106
EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad = null,
107107
EventHandler<HtmlImageLoadEventArgs> imageLoad = null)
108108
{
109+
using (var container = await CreateHtmlContainer(html, width, cssData, stylesheetLoad, imageLoad))
110+
{
111+
var bitmap = new SKBitmap(width, height ?? (int)container.ActualSize.Height);
112+
var canvas = new SKCanvas(bitmap);
113+
await DrawHtmlToCanvas(container, canvas);
114+
bitmap.Encode(outputStream, imageFormat, quality);
109115

110-
var bitmap = new SKBitmap((int)size.Width, (int)size.Height);
111-
var canvas = new SKCanvas(bitmap);
112-
113-
// add rendered image
114-
await DrawSvgAsync(canvas, html, size, cssData, stylesheetLoad, imageLoad);
115-
bitmap.Encode(outputStream, imageFormat, quality);
116-
117-
return canvas;
116+
}
118117
}
119118

120119
/// <summary>
121-
/// Create image pages from given HTML and appends them to the provided image document.<br/>
120+
/// Creates a html container for the suupplied content. Given a width, this will
121+
/// determine the actual height.
122122
/// </summary>
123-
/// <param name="canvas">canvas to draw to</param>
124-
/// <param name="html">HTML source to create image from</param>
125-
/// <param name="cssData">optional: the style to use for html rendering (default - use W3 default style)</param>
126-
/// <param name="stylesheetLoad">optional: can be used to overwrite stylesheet resolution logic</param>
127-
/// <param name="imageLoad">optional: can be used to overwrite image resolution logic</param>
128-
/// <returns>the generated image of the html</returns>
129-
public static async Task DrawSvgAsync(
130-
SKCanvas canvas,
131-
string html,
132-
SKSize size,
133-
CssData cssData = null,
134-
EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad = null,
135-
EventHandler<HtmlImageLoadEventArgs> imageLoad = null)
123+
private static async Task<HtmlContainer> CreateHtmlContainer(string html,
124+
int width,
125+
CssData? cssData = null,
126+
EventHandler<HtmlStylesheetLoadEventArgs>? stylesheetLoad = null,
127+
EventHandler<HtmlImageLoadEventArgs>? imageLoad = null)
136128
{
137-
using var container = new HtmlContainer();
129+
var container = new HtmlContainer();
130+
138131
if (stylesheetLoad != null)
139132
container.StylesheetLoad += stylesheetLoad;
140133
if (imageLoad != null)
141134
container.ImageLoad += imageLoad;
142135

143-
container.Location = new SKPoint(0, 0);
144-
//container.MaxSize = size;
145-
container.MaxSize = new SKSize(size.Width, 0);
146-
container.PageSize = size;
147-
container.MarginBottom = 0;
148-
container.MarginLeft = 0;
149-
container.MarginRight = 0;
150-
container.MarginTop = 0;
151-
container.ScrollOffset = new SKPoint(0, 0);
136+
container.MaxSize = new SKSize(width, 0);
137+
await container.SetHtml(html, cssData!);
138+
139+
// determine the actual height of the html we're rendering.
140+
var docImageInfo = new SKImageInfo(width, width);
141+
using (var s = SKSurface.Create(docImageInfo))
142+
using (var g = s.Canvas)
143+
{
144+
await container.PerformLayout(g);
145+
}
152146

153-
await container.SetHtml(html, cssData);
147+
container.PageSize = container.ActualSize;
148+
return container;
149+
}
154150

155-
// layout the HTML with the page width restriction to know how many pages are required
151+
private static async Task DrawHtmlToCanvas(HtmlContainer container, SKCanvas canvas)
152+
{
156153
await container.PerformLayout(canvas);
157154
await container.PerformPaint(canvas);
158155
}

0 commit comments

Comments
 (0)