markus / FinalService / FinalServiceBase / MarkupToPDF / Common / XamlToPngConverter.cs @ 490208bd
이력 | 보기 | 이력해설 | 다운로드 (3.81 KB)
1 |
|
---|---|
2 |
using System; |
3 |
using System.Collections.Generic; |
4 |
using System.IO; |
5 |
using System.Reflection; |
6 |
using System.Threading; |
7 |
using System.Windows; |
8 |
using System.Windows.Markup; |
9 |
using System.Windows.Media; |
10 |
using System.Windows.Media.Imaging; |
11 |
|
12 |
|
13 |
namespace XAMLtoPNG |
14 |
{ |
15 |
public enum ScaleTO |
16 |
{ |
17 |
OriginalSize=1, |
18 |
TargetSize=2 |
19 |
} |
20 |
|
21 |
/// <summary> |
22 |
/// Source: http://blog.galasoft.ch/archive/2008/10/10/converting-and-customizing-xaml-to-png-with-server-side-wpf.aspx |
23 |
/// </summary> |
24 |
public class XamlToPngConverter |
25 |
{ |
26 |
public void Convert(Stream xamlInput, |
27 |
double width, |
28 |
double height, |
29 |
double dpiX, |
30 |
double dpiY, |
31 |
ScaleTO thisScale, |
32 |
Stream pngOutput) |
33 |
{ |
34 |
try |
35 |
{ |
36 |
// Round width and height to simplify |
37 |
width = Math.Round(width); |
38 |
height = Math.Round(height); |
39 |
|
40 |
Thread pngCreationThread = new Thread((ThreadStart) delegate() |
41 |
{ |
42 |
FrameworkElement element = null; |
43 |
|
44 |
try |
45 |
{ |
46 |
var inputElement = XamlReader.Load(xamlInput) as FrameworkElement; |
47 |
|
48 |
var viewbox = new System.Windows.Controls.Viewbox(); |
49 |
viewbox.Stretch = Stretch.Fill; |
50 |
viewbox.Child = inputElement; |
51 |
viewbox.Width = width; |
52 |
viewbox.Height = height; |
53 |
|
54 |
element = viewbox; |
55 |
} |
56 |
catch (XamlParseException) |
57 |
{ |
58 |
} |
59 |
|
60 |
if (element != null) |
61 |
{ |
62 |
Size renderingSize = new Size(width, height); |
63 |
element.Measure(renderingSize); |
64 |
Rect renderingRectangle = new Rect(renderingSize); |
65 |
element.Arrange(renderingRectangle); |
66 |
|
67 |
BitmapSource xamlBitmap = RenderToBitmap(element, width, height, dpiX, dpiY, thisScale); |
68 |
try |
69 |
{ |
70 |
PngBitmapEncoder enc = new PngBitmapEncoder(); |
71 |
enc.Frames.Add(BitmapFrame.Create(xamlBitmap)); |
72 |
enc.Save(pngOutput); |
73 |
} |
74 |
catch (ObjectDisposedException) |
75 |
{ |
76 |
// IF the operation lasted too long, the object might be disposed already |
77 |
} |
78 |
} |
79 |
}); |
80 |
|
81 |
pngCreationThread.IsBackground = true; |
82 |
pngCreationThread.SetApartmentState(ApartmentState.STA); |
83 |
pngCreationThread.Start(); |
84 |
pngCreationThread.Join(); |
85 |
} |
86 |
catch (Exception Exp) |
87 |
{ |
88 |
throw Exp; |
89 |
} |
90 |
|
91 |
try |
92 |
{ |
93 |
if (pngOutput.Length == 0) |
94 |
{ |
95 |
throw new TimeoutException(); |
96 |
} |
97 |
} |
98 |
catch (ObjectDisposedException) |
99 |
{ |
100 |
// If the object was disposed, it means that the Stream is ready. |
101 |
} |
102 |
} |
103 |
|
104 |
private BitmapSource RenderToBitmap(FrameworkElement target, |
105 |
double width, |
106 |
double height, |
107 |
double dpiX, |
108 |
double dpiY, |
109 |
ScaleTO thisScale) |
110 |
{ |
111 |
Rect bounds; |
112 |
|
113 |
switch (thisScale) |
114 |
{ |
115 |
case ScaleTO.OriginalSize: |
116 |
bounds = VisualTreeHelper.GetDescendantBounds(target); |
117 |
break; |
118 |
case ScaleTO.TargetSize: |
119 |
bounds = new Rect(0, 0, width,height); |
120 |
break; |
121 |
default: |
122 |
throw new ArgumentException(string.Format("The scaling mode: {0} is not supported.", thisScale.ToString())); |
123 |
} |
124 |
|
125 |
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int) target.ActualWidth, |
126 |
(int)target.ActualHeight, dpiX, dpiY, PixelFormats.Pbgra32); |
127 |
|
128 |
DrawingVisual visual = new DrawingVisual(); |
129 |
using (DrawingContext context = visual.RenderOpen()) |
130 |
{ |
131 |
VisualBrush brush = new VisualBrush(target); |
132 |
context.DrawRectangle(brush, null, new Rect(new Point(), bounds.Size)); |
133 |
} |
134 |
|
135 |
renderBitmap.Render(visual); |
136 |
return renderBitmap; |
137 |
} |
138 |
} |
139 |
} |