Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorRenderingWpf/Wpf/WpfImageRendering.cs @ 13419

Last change on this file since 13419 was 12762, checked in by aballeit, 9 years ago

#2283 GUI updates, Tree-chart, MCTS Version 2 (prune leaves)

File size: 18.7 KB
Line 
1using System;
2using System.IO;
3using System.Xml;
4using System.Linq;
5using System.Text;
6using System.Diagnostics;
7using System.Collections.Generic;
8
9using System.Windows;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12
13using SharpVectors.Net;
14using SharpVectors.Dom.Svg;
15
16namespace SharpVectors.Renderers.Wpf
17{
18    public sealed class WpfImageRendering : WpfRendering
19    {
20        #region Private Fields
21
22        private WpfDrawingRenderer _embeddedRenderer;
23
24        #endregion
25
26        #region Constructors and Destructor
27
28        public WpfImageRendering(SvgElement element)
29            : base(element)
30    {
31    }
32
33        #endregion
34
35        #region Public Methods
36
37        public override void BeforeRender(WpfDrawingRenderer renderer)
38        {
39            base.BeforeRender(renderer);
40        }
41
42        public override void Render(WpfDrawingRenderer renderer)
43        {
44            WpfDrawingContext context    = renderer.Context;
45            SvgImageElement imageElement = (SvgImageElement)_svgElement;
46
47            double width  = imageElement.Width.AnimVal.Value;
48            double height = imageElement.Height.AnimVal.Value;
49
50            Rect destRect = new Rect(imageElement.X.AnimVal.Value, imageElement.Y.AnimVal.Value,
51                width, height);
52
53            ImageSource imageSource = null;
54            if (imageElement.IsSvgImage)
55            {
56                SvgWindow wnd = GetSvgWindow();
57                //_embeddedRenderer.BackColor = Color.Empty; 
58                _embeddedRenderer.Render(wnd.Document);
59
60                DrawingGroup imageGroup = _embeddedRenderer.Drawing as DrawingGroup;
61                if (imageGroup != null &&
62                    (imageGroup.Children != null && imageGroup.Children.Count == 1))
63                {
64                    DrawingGroup drawImage = imageGroup.Children[0] as DrawingGroup;
65                    if (drawImage != null)
66                    {
67                        if (drawImage.ClipGeometry != null)
68                        {
69                            drawImage.ClipGeometry = null;
70                        }
71
72                        imageSource = new DrawingImage(drawImage);
73                    }
74                    else
75                    {
76                        if (imageGroup.ClipGeometry != null)
77                        {
78                            imageGroup.ClipGeometry = null;
79                        }
80
81                        imageSource = new DrawingImage(imageGroup);
82                    }
83                }
84                else
85                {
86                    imageSource = new DrawingImage(_embeddedRenderer.Drawing);
87                }
88
89                if (_embeddedRenderer != null)
90                {
91                    _embeddedRenderer.Dispose();
92                    _embeddedRenderer = null;
93                }
94            }
95            else
96            {
97                imageSource = GetBitmapSource(imageElement, context);
98            }
99           
100            if (imageSource == null)
101            {
102                return;
103            }
104
105            //TODO--PAUL: Set the DecodePixelWidth/DecodePixelHeight?
106
107            // Freeze the DrawingImage for performance benefits.
108            imageSource.Freeze();
109
110            DrawingGroup drawGroup = null;
111
112            ISvgAnimatedPreserveAspectRatio animatedAspectRatio = imageElement.PreserveAspectRatio;
113            if (animatedAspectRatio != null && animatedAspectRatio.AnimVal != null)
114            {
115                SvgPreserveAspectRatio aspectRatio = animatedAspectRatio.AnimVal as SvgPreserveAspectRatio;
116                SvgPreserveAspectRatioType aspectRatioType =
117                    (aspectRatio != null) ? aspectRatio.Align : SvgPreserveAspectRatioType.Unknown;
118                if (aspectRatio != null && aspectRatioType != SvgPreserveAspectRatioType.None &&
119                    aspectRatioType != SvgPreserveAspectRatioType.Unknown)
120                {                     
121                    double imageWidth  = imageSource.Width;
122                    double imageHeight = imageSource.Height;
123
124                    double viewWidth  = destRect.Width;
125                    double viewHeight = destRect.Height;
126
127                    SvgMeetOrSlice meetOrSlice = aspectRatio.MeetOrSlice;
128                    if (meetOrSlice == SvgMeetOrSlice.Meet)
129                    {
130                        if (imageWidth <= viewWidth && imageHeight <= viewHeight)
131                        {
132                            destRect = this.GetBounds(destRect,
133                                new Size(imageWidth, imageHeight), aspectRatioType);
134                        }
135                        else
136                        {
137                            Transform viewTransform = this.GetAspectRatioTransform(aspectRatio,
138                              new SvgRect(0, 0, imageWidth, imageHeight),
139                              new SvgRect(destRect.X, destRect.Y, destRect.Width, destRect.Height));
140                            //Transform scaleTransform = this.FitToViewbox(aspectRatio,
141                            //  new SvgRect(destRect.X, destRect.Y, imageWidth, imageHeight),
142                            //  new SvgRect(destRect.X, destRect.Y, destRect.Width, destRect.Height));
143
144                            if (viewTransform != null)
145                            {
146                                drawGroup = new DrawingGroup();
147                                drawGroup.Transform = viewTransform;
148
149                                DrawingGroup lastGroup = context.Peek();
150                                Debug.Assert(lastGroup != null);
151
152                                if (lastGroup != null)
153                                {
154                                    lastGroup.Children.Add(drawGroup);
155                                }
156
157                                destRect = this.GetBounds(destRect,
158                                    new Size(imageWidth, imageHeight), aspectRatioType);
159
160                                // The origin is already handled by the view transform...
161                                destRect.X = 0;
162                                destRect.Y = 0;
163                            }
164                        }
165                    }
166                    else if (meetOrSlice == SvgMeetOrSlice.Slice)
167                    {   
168                    }
169                }
170            }
171
172            ImageDrawing drawing = new ImageDrawing(imageSource, destRect);
173
174            float opacityValue = -1;
175
176            string opacity = imageElement.GetAttribute("opacity");
177            if (opacity != null && opacity.Length > 0)
178            {
179                opacityValue = (float)SvgNumber.ParseNumber(opacity);
180                opacityValue = Math.Min(opacityValue, 1);
181                opacityValue = Math.Max(opacityValue, 0);
182            }
183
184            Geometry clipGeom   = this.ClipGeometry;
185            Transform transform = this.Transform;
186
187            if (drawGroup == null)
188            {
189                drawGroup = context.Peek();
190            }
191            Debug.Assert(drawGroup != null);
192            if (drawGroup != null)
193            {
194                if (opacityValue >= 0 || (clipGeom != null && !clipGeom.IsEmpty()) ||
195                    (transform != null && !transform.Value.IsIdentity))
196                {
197                    DrawingGroup clipGroup = new DrawingGroup();
198                    if (opacityValue >= 0)
199                    {
200                        clipGroup.Opacity = opacityValue;
201                    }
202                    if (clipGeom != null)
203                    {
204                        SvgUnitType clipUnits = this.ClipUnits;
205                        if (clipUnits == SvgUnitType.ObjectBoundingBox)
206                        {
207                            Rect drawingBounds = drawing.Bounds;
208
209                            TransformGroup transformGroup = new TransformGroup();
210
211                            // Scale the clip region (at (0, 0)) and translate to the top-left corner of the target.
212                            transformGroup.Children.Add(
213                                new ScaleTransform(drawingBounds.Width, drawingBounds.Height));
214                            transformGroup.Children.Add(
215                                new TranslateTransform(drawingBounds.X, drawingBounds.Y));
216
217                            clipGeom.Transform = transformGroup;
218                        }
219
220                        clipGroup.ClipGeometry = clipGeom;
221                    }
222                    if (transform != null)
223                    {
224                        clipGroup.Transform = transform;
225                    }
226
227                    clipGroup.Children.Add(drawing);
228                    drawGroup.Children.Add(clipGroup);
229                }
230                else
231                {
232                    drawGroup.Children.Add(drawing);
233                }
234            }
235        }
236
237        public override void AfterRender(WpfDrawingRenderer renderer)
238        {
239            base.AfterRender(renderer);
240        }
241
242        #endregion
243
244        #region Private Methods
245
246        private SvgWindow GetSvgWindow()
247        {
248            if (_embeddedRenderer == null)
249            {
250                _embeddedRenderer = new WpfDrawingRenderer();
251            }
252
253            SvgImageElement iElm = (SvgImageElement)this.Element;
254            SvgWindow wnd = iElm.SvgWindow;
255            wnd.Renderer  = _embeddedRenderer;
256
257            _embeddedRenderer.Window = wnd;
258
259            return wnd;
260        }
261
262        private ImageSource GetBitmapSource(SvgImageElement element, WpfDrawingContext context)
263        {
264            BitmapSource bitmapSource = this.GetBitmap(element, context);
265            if (bitmapSource == null)
266            {
267                return bitmapSource;
268            }
269
270            SvgColorProfileElement colorProfile = (SvgColorProfileElement)element.ColorProfile;
271            if (colorProfile == null)
272            {
273                return bitmapSource;
274            }
275            else
276            {
277                BitmapFrame bitmapSourceFrame   = BitmapFrame.Create(bitmapSource);
278                ColorContext sourceColorContext = null;
279                IList<ColorContext> colorContexts = bitmapSourceFrame.ColorContexts;
280                if (colorContexts != null && colorContexts.Count != 0)
281                {
282                    sourceColorContext = colorContexts[0];
283                }
284                else
285                {
286                    sourceColorContext = new ColorContext(bitmapSource.Format);
287                    //sourceColorContext = new ColorContext(PixelFormats.Default);
288                }
289
290                SvgUriReference svgUri = colorProfile.UriReference;
291                Uri profileUri = new Uri(svgUri.AbsoluteUri);
292
293                ColorContext destColorContext = new ColorContext(profileUri);
294                ColorConvertedBitmap convertedBitmap = new ColorConvertedBitmap(bitmapSource,
295                    sourceColorContext, destColorContext, bitmapSource.Format);
296
297                return convertedBitmap;
298            }
299        }
300
301        private BitmapSource GetBitmap(SvgImageElement element, WpfDrawingContext context)
302        {
303            if (element.IsSvgImage)
304            {
305                return null;
306            }
307
308            if (!element.Href.AnimVal.StartsWith("data:"))
309            {
310                SvgUriReference svgUri = element.UriReference;
311                string absoluteUri = svgUri.AbsoluteUri;
312                if (String.IsNullOrEmpty(absoluteUri))
313                {
314                    return null; // most likely, the image does not exist...
315                }
316
317                Uri imageUri = new Uri(svgUri.AbsoluteUri);
318                if (imageUri.IsFile)
319                {
320                    if (File.Exists(imageUri.LocalPath))
321                    {
322                        BitmapImage imageSource = new BitmapImage();
323
324                        imageSource.BeginInit();
325                        imageSource.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
326                        imageSource.UriSource     = imageUri;
327                        imageSource.EndInit();
328
329                        return imageSource;
330                    }
331
332                    return null;
333                }
334                else
335                {
336                    Stream stream = svgUri.ReferencedResource.GetResponseStream();
337
338                    BitmapImage imageSource = new BitmapImage();
339                    imageSource.BeginInit();
340                    imageSource.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
341                    imageSource.StreamSource  = stream;
342                    imageSource.EndInit();
343
344                    return imageSource;
345                }
346            }
347            else
348            {
349                WpfEmbeddedImageVisitor imageVisitor = context.ImageVisitor;
350                if (imageVisitor != null)
351                {
352                    BitmapSource visitorSource = imageVisitor.Visit(element, context);
353                    if (visitorSource != null)
354                    {
355                        return visitorSource;
356                    }
357                }
358
359                string sURI    = element.Href.AnimVal;
360                int nColon     = sURI.IndexOf(":");
361                int nSemiColon = sURI.IndexOf(";");
362                int nComma     = sURI.IndexOf(",");
363
364                string sMimeType = sURI.Substring(nColon + 1, nSemiColon - nColon - 1);
365
366                string sContent  = sURI.Substring(nComma + 1);
367                byte[] bResult   = Convert.FromBase64CharArray(sContent.ToCharArray(),
368                    0, sContent.Length);
369
370                BitmapImage imageSource = new BitmapImage();
371                imageSource.BeginInit();
372                imageSource.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
373                imageSource.StreamSource  = new MemoryStream(bResult);
374                imageSource.EndInit();
375
376                return imageSource;
377            }
378        }
379
380        #region GetBounds Method
381
382        private Rect GetBounds(Rect bounds, Size textSize, SvgPreserveAspectRatioType alignment)
383        {
384            switch (alignment)
385            {
386                case SvgPreserveAspectRatioType.XMinYMin:  //Top-Left
387                    {
388                        return new Rect(bounds.X, bounds.Y,
389                            textSize.Width, textSize.Height);
390                    }
391                case SvgPreserveAspectRatioType.XMidYMin: //Top-Center
392                    {
393                        return new Rect(bounds.X +
394                            (bounds.Width - textSize.Width) / 2f,
395                            bounds.Y, textSize.Width, textSize.Height);
396                    }
397                case SvgPreserveAspectRatioType.XMaxYMin: //Top-Right
398                    {
399                        return new Rect(bounds.Right - textSize.Width,
400                            bounds.Y, textSize.Width, textSize.Height);
401                    }
402                case SvgPreserveAspectRatioType.XMinYMid: //Middle-Left
403                    {
404                        return new Rect(bounds.X, bounds.Y +
405                            (bounds.Height - textSize.Height) / 2f, textSize.Width,
406                            textSize.Height);
407                    }
408                case SvgPreserveAspectRatioType.XMidYMid:  //Middle-Center
409                    {
410                        return new Rect(bounds.X + bounds.Width / 2f - textSize.Width / 2f,
411                            bounds.Y + bounds.Height / 2f - textSize.Height / 2f,
412                            textSize.Width, textSize.Height);
413                    }
414                case SvgPreserveAspectRatioType.XMaxYMid: //Middle-Right
415                    {
416                        return new Rect(bounds.Right - textSize.Width,
417                            bounds.Y + bounds.Height / 2f - textSize.Height / 2f,
418                            textSize.Width, textSize.Height);
419                    }
420                case SvgPreserveAspectRatioType.XMinYMax: //Bottom-Left
421                    {
422                        return new Rect(bounds.X,
423                            bounds.Bottom - textSize.Height,
424                            textSize.Width, textSize.Height);
425                    }
426                case SvgPreserveAspectRatioType.XMidYMax:  //Bottom-Center
427                    {
428                        return new Rect(bounds.X +
429                            (bounds.Width - textSize.Width) / 2f,
430                            bounds.Bottom - textSize.Height,
431                            textSize.Width, textSize.Height);
432                    }
433                case SvgPreserveAspectRatioType.XMaxYMax:  // Bottom-Right
434                    {
435                        return new Rect(bounds.Right - textSize.Width,
436                            bounds.Bottom - textSize.Height,
437                            textSize.Width, textSize.Height);
438                    }
439            }
440
441            return bounds;
442        }
443
444        private Transform GetAspectRatioTransform(SvgPreserveAspectRatio spar,
445            SvgRect sourceBounds, SvgRect elementBounds)
446        {
447            double[] transformArray = spar.FitToViewBox(sourceBounds, elementBounds);
448
449            double translateX = transformArray[0];
450            double translateY = transformArray[1];
451            double scaleX = transformArray[2];
452            double scaleY = transformArray[3];
453
454            Transform translateMatrix = null;
455            Transform scaleMatrix = null;
456            if ((float)translateX >= 0 && (float)translateY >= 0)
457            {
458                translateMatrix = new TranslateTransform(translateX, translateY);
459            }
460            if ((float)scaleX != 1.0f && (float)scaleY != 1.0)
461            {
462                scaleMatrix = new ScaleTransform(scaleX, scaleY);
463            }
464
465            if (translateMatrix != null && scaleMatrix != null)
466            {
467                // Create a TransformGroup to contain the transforms
468                // and add the transforms to it.
469                TransformGroup transformGroup = new TransformGroup();
470                transformGroup.Children.Add(scaleMatrix);
471                transformGroup.Children.Add(translateMatrix);
472
473                return transformGroup;
474            }
475            else if (translateMatrix != null)
476            {
477                return translateMatrix;
478            }
479            else if (scaleMatrix != null)
480            {
481                return scaleMatrix;
482            }
483
484            return null;
485        }
486
487        #endregion
488
489        #endregion
490    }
491}
Note: See TracBrowser for help on using the repository browser.