markus / FinalService / FinalServiceBase / MarkupToPDF / Common / XamlToPngConverter.cs @ 490208bd
이력 | 보기 | 이력해설 | 다운로드 (3.81 KB)
1 | 42d49521 | taeseongkim | |
---|---|---|---|
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 | } |