Exemple #1
0
        public static void ShowFileExportSpecificDialog(GraphDocument doc)
        {
            object resopt = _graphExportOptionsToFile;

            if (Current.Gui.ShowDialog(ref resopt, "Choose export options"))
            {
                _graphExportOptionsToFile = (Graph.Gdi.GraphExportOptions)resopt;
            }
            else
            {
                return;
            }
            ShowFileExportDialog(doc, _graphExportOptionsToFile);
        }
Exemple #2
0
        public static void ShowFileExportDialog(GraphDocument doc, Altaxo.Graph.Gdi.GraphExportOptions graphExportOptions)
        {
            var saveOptions = new Altaxo.Gui.SaveFileOptions();
            var list        = GetFileFilterString(graphExportOptions.ImageFormat);

            foreach (var entry in list)
            {
                saveOptions.AddFilter(entry.Key, entry.Value);
            }
            saveOptions.FilterIndex      = 0;
            saveOptions.RestoreDirectory = true;

            if (Current.Gui.ShowSaveFileDialog(saveOptions))
            {
                using (Stream myStream = new FileStream(saveOptions.FileName, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    new Gui.Graph.Graph3D.Common.D3D10BitmapExporter().ExportAsImageToStream(doc, graphExportOptions, myStream);
                    myStream.Close();
                } // end openfile ok
            }     // end dlgresult ok
        }
Exemple #3
0
        /// <summary>
        /// Gets the content of an image referenced in a <see cref="TextDocument"/>.
        /// </summary>
        /// <param name="stream">The stream to copy the content to.</param>
        /// <param name="url">The URL of the image, as occuring in a link tag in the <see cref="TextDocument"/>.</param>
        /// <param name="targetResolution">The target resolution in dpi.</param>
        /// <param name="altaxoFolderLocation">The folder location of the <see cref="TextDocument"/> It is used for searching graphs relative to that location.</param>
        /// <param name="localImages">The local images of the <see cref="TextDocument"/>.</param>
        /// <returns>A tuple of tree values. isStreamImage is true if the url could be resolved to an image. extension is the file extension of the image. errorMessage is unequal to null if an error has occured. In this case the content of <paramref name="stream"/> was not set.</returns>
        public ImageRenderToStreamResult GetImageStream(System.IO.Stream stream, string url, double targetResolution, string altaxoFolderLocation, IReadOnlyDictionary <string, Altaxo.Graph.MemoryStreamImageProxy> localImages)
        {
            if (url.StartsWith(ImagePretext.GraphRelativePathPretext))
            {
                string graphName = url.Substring(ImagePretext.GraphRelativePathPretext.Length);

                var grp = FindGraphWithUrl(graphName, altaxoFolderLocation);

                if (grp is Altaxo.Graph.Gdi.GraphDocument graph)
                {
                    var options = new Altaxo.Graph.Gdi.GraphExportOptions()
                    {
                        SourceDpiResolution      = targetResolution,
                        DestinationDpiResolution = targetResolution,
                    };

                    var(pixelsX, pixelsY) = Altaxo.Graph.Gdi.GraphDocumentExportActions.RenderToStream(graph, stream, options);
                    return(new ImageRenderToStreamResult(graph.Name, ".png",
                                                         options.DestinationDpiResolution, options.DestinationDpiResolution,
                                                         pixelsX, pixelsY));
                }
                else if (grp is Altaxo.Graph.Graph3D.GraphDocument graph3D)
                {
                    var options = new Altaxo.Graph.Gdi.GraphExportOptions()
                    {
                        SourceDpiResolution      = targetResolution,
                        DestinationDpiResolution = targetResolution,
                    };

                    var(pixelsX, pixelsY) = Altaxo.Graph.Graph3D.GraphDocumentExportActions.RenderToStream(graph3D, stream, options);
                    if (pixelsX > 0 && pixelsY > 0)
                    {
                        return(new ImageRenderToStreamResult(graph3D.Name, ".png",
                                                             options.DestinationDpiResolution, options.DestinationDpiResolution,
                                                             pixelsX, pixelsY));
                    }
                    else
                    {
                        return(new ImageRenderToStreamResult("ERROR: NO RENDERER FOR 3D GRAPHS FOUND!"));
                    }
                }
                else
                {
                    return(new ImageRenderToStreamResult(string.Format("ERROR: GRAPH '{0}' NOT FOUND!", graphName)));
                }
            }
            else if (url.StartsWith(ImagePretext.ResourceImagePretext))
            {
                string name     = url.Substring(ImagePretext.ResourceImagePretext.Length);
                var    inStream = Current.ResourceService.GetResourceStream(name);

                if (null != inStream)
                {
                    string extension;
                    int    pixelsX, pixelsY;
                    double dpiX, dpiY;

                    using (var image = System.Drawing.Image.FromStream(inStream))
                    {
                        pixelsX   = image.Width;
                        pixelsY   = image.Height;
                        dpiX      = image.HorizontalResolution;
                        dpiY      = image.VerticalResolution;
                        extension = Altaxo.Drawing.ImageExtensions.GetFileExtension(image);
                    }
                    inStream.Seek(0, SeekOrigin.Begin);

                    inStream.CopyTo(stream);
                    return(new ImageRenderToStreamResult(url, extension, dpiX, dpiY, pixelsX, pixelsY));
                }
                else // If it doesn't work with a stream, we try to get a bitmap
                {
                    System.Drawing.Bitmap bitmap = null;
                    try { bitmap = Current.ResourceService.GetBitmap(name); } catch { }

                    if (null != bitmap)
                    {
                        bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                        return(new ImageRenderToStreamResult(url, ".png", bitmap.HorizontalResolution, bitmap.VerticalResolution, bitmap.Width, bitmap.Height));
                    }
                    else
                    {
                        return(new ImageRenderToStreamResult(string.Format("Resource image '{0}' not found!", name)));
                    }
                }
            }
            else if (url.StartsWith(ImagePretext.LocalImagePretext))
            {
                string name = url.Substring(ImagePretext.LocalImagePretext.Length);

                if (null != localImages && localImages.TryGetValue(name, out var localImageStreamProxy))
                {
                    var inStream  = localImageStreamProxy.GetContentStream();
                    var extension = localImageStreamProxy.Extension;
                    inStream.CopyTo(stream);
                    return(new ImageRenderToStreamResult(localImageStreamProxy.Name, localImageStreamProxy.Extension,
                                                         localImageStreamProxy.ResolutionDpi.X, localImageStreamProxy.ResolutionDpi.Y,
                                                         localImageStreamProxy.ImageSizePixels.X, localImageStreamProxy.ImageSizePixels.Y));
                }
                else
                {
                    return(new ImageRenderToStreamResult(string.Format("ERROR: LOCAL IMAGE '{0}' NOT FOUND!", name)));
                }
            }
            else
            {
                if (string.IsNullOrEmpty(url) || !Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
                {
                    return(new ImageRenderToStreamResult(string.Format("Url empty or malformed: {0}", url)));
                }
                else
                {
                    return(new ImageRenderToStreamResult(string.Format("Does not understand this kind of Url: {0}", url)));
                }
            }
        }
Exemple #4
0
		public static void ShowFileExportSpecificDialog(GraphDocument doc)
		{
			object resopt = _graphExportOptionsToFile;
			if (Current.Gui.ShowDialog(ref resopt, "Choose export options"))
			{
				_graphExportOptionsToFile = (Graph.Gdi.GraphExportOptions)resopt;
			}
			else
			{
				return;
			}
			ShowFileExportDialog(doc, _graphExportOptionsToFile);
		}
Exemple #5
0
        /// <summary>
        /// Saves the project item as image to the provided stream.
        /// </summary>
        /// <param name="item">The item to export, for instance an item of type <see cref="Altaxo.Graph.Gdi.GraphDocument"/> or <see cref="Altaxo.Graph.Graph3D.GraphDocument"/>.</param>
        /// <param name="options">The export options.</param>
        /// <param name="toStream">The stream to save the image to.</param>
        public (int PixelsX, int PixelsY) ExportAsImageToStream(Altaxo.Main.IProjectItem item, Altaxo.Graph.Gdi.GraphExportOptions options, System.IO.Stream toStream)
        {
            // SharpDX.Configuration.EnableObjectTracking = true;
            // var listOfActiveObjects = SharpDX.Diagnostics.ObjectTracker.FindActiveObjects();

            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }
            if (!(item is Altaxo.Graph.Graph3D.GraphDocument))
            {
                throw new ArgumentException(string.Format("Expected item of type {0}, but it is of type {1}", typeof(Altaxo.Graph.Graph3D.GraphDocument), item.GetType()));
            }
            var doc = (Altaxo.Graph.Graph3D.GraphDocument)item;

            double sourceDpi = options.SourceDpiResolution;

            Viewing.D3D10Scene   scene = null;
            D3D10GraphicsContext g     = null;

            try
            {
                scene = new Viewing.D3D10Scene();
                g     = new D3D10GraphicsContext();

                doc.Paint(g);

                var matrix = doc.Camera.LookAtRHMatrix;

                var rect   = new RectangleD3D(PointD3D.Empty, doc.RootLayer.Size);
                var bounds = RectangleD3D.NewRectangleIncludingAllPoints(rect.Vertices.Select(x => matrix.Transform(x)));

                int pixelsX = (int)Math.Ceiling(sourceDpi * bounds.SizeX / 72.0);
                pixelsX = (int)(4 * Math.Ceiling((pixelsX + 3) / 4.0));

                int pixelsY = (int)(sourceDpi * bounds.SizeY / 72.0);

                double aspectRatio = pixelsY / (double)pixelsX;

                var sceneCamera = doc.Camera;

                if (sceneCamera is OrthographicCamera)
                {
                    var orthoCamera = (OrthographicCamera)sceneCamera;
                    orthoCamera = (OrthographicCamera)orthoCamera.WithWidthAtZNear(bounds.SizeX);

                    double offsX = -(1 + 2 * bounds.X / bounds.SizeX);
                    double offsY = -(1 + 2 * bounds.Y / bounds.SizeY);
                    sceneCamera = orthoCamera.WithScreenOffset(new PointD2D(offsX, offsY));
                }
                else if (sceneCamera is PerspectiveCamera)
                {
                    var viewProj     = sceneCamera.GetViewProjectionMatrix(1);                                                    // here we transform the points with AspectRatio=1, in order to get the AspectRatio of the ScreenBounds
                    var screenBounds = RectangleD3D.NewRectangleIncludingAllPoints(rect.Vertices.Select(x => viewProj.Transform(x)));
                    aspectRatio  = screenBounds.SizeY / screenBounds.SizeX;                                                       // this is the aspectRatio of our image
                    viewProj     = sceneCamera.GetViewProjectionMatrix(aspectRatio);                                              // now we get the transform with our aspectRatio determined above
                    screenBounds = RectangleD3D.NewRectangleIncludingAllPoints(rect.Vertices.Select(x => viewProj.Transform(x))); // this are our actual screenBounds, of course in relative screen coordinates, thus the ratio of sizeX and sizeY should now be 1

                    double scaleFactor = 2 / screenBounds.SizeX;                                                                  // since SizeX and SizeY should now be the same, we could have used SizeY alternatively
                    double offsX       = -(1 + scaleFactor * screenBounds.X);
                    double offsY       = -(1 + scaleFactor * screenBounds.Y);

                    pixelsY = (int)(4 * Math.Ceiling((aspectRatio * pixelsX + 3) / 4.0)); // now calculate the size of the image in y direction from the aspectRatio

                    var perspCamera = (PerspectiveCamera)sceneCamera;

                    sceneCamera = perspCamera.WithWidthAtZNear(perspCamera.WidthAtZNear / scaleFactor);
                    sceneCamera = sceneCamera.WithScreenOffset(new PointD2D(offsX, offsY));
                }
                else
                {
                    throw new NotImplementedException();
                }

                scene.SetCamera(sceneCamera);
                scene.SetLighting(doc.Lighting);
                scene.SetDrawing(g);

                Export(pixelsX, pixelsY, scene, options, toStream);
                return(pixelsX, pixelsY);
            }
            finally
            {
                Disposer.RemoveAndDispose(ref g);
                Disposer.RemoveAndDispose(ref scene);
            }
        }
Exemple #6
0
        public void Export(int sizeX, int sizeY, ID3D10Scene scene, Altaxo.Graph.Gdi.GraphExportOptions options, System.IO.Stream toStream)
        {
            Device           device           = null;
            Texture2D        renderTarget     = null;
            Texture2D        renderTarget2    = null;
            Texture2D        depthStencil     = null;
            RenderTargetView renderTargetView = null;
            DepthStencilView depthStencilView = null;

            try
            {
                //device = new Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0);
                device = D3D10DeviceFactory.Instance.BorrowDevice();
                // try to get the highest MSAA level with the highest quality
                int sampleCount        = 32;
                int qlevel_sampleCount = 0;

                for (; sampleCount >= 0; sampleCount /= 2)
                {
                    if (0 != (qlevel_sampleCount = device.CheckMultisampleQualityLevels(Format.B8G8R8A8_UNorm, sampleCount))) // quality level for sample count
                    {
                        break;
                    }
                }

                var colordesc = new Texture2DDescription
                {
                    BindFlags         = BindFlags.RenderTarget | BindFlags.ShaderResource,
                    Format            = Format.B8G8R8A8_UNorm_SRgb,
                    Width             = sizeX,
                    Height            = sizeY,
                    MipLevels         = 1,
                    SampleDescription = new SampleDescription(sampleCount, qlevel_sampleCount - 1),
                    Usage             = ResourceUsage.Default,
                    OptionFlags       = ResourceOptionFlags.Shared,
                    CpuAccessFlags    = CpuAccessFlags.None,
                    ArraySize         = 1
                };

                var depthdesc = new Texture2DDescription
                {
                    BindFlags         = BindFlags.DepthStencil,
                    Format            = Format.D32_Float_S8X24_UInt,
                    Width             = sizeX,
                    Height            = sizeY,
                    MipLevels         = 1,
                    SampleDescription = new SampleDescription(sampleCount, qlevel_sampleCount - 1),
                    Usage             = ResourceUsage.Default,
                    OptionFlags       = ResourceOptionFlags.None,
                    CpuAccessFlags    = CpuAccessFlags.None,
                    ArraySize         = 1,
                };

                renderTarget     = new Texture2D(device, colordesc);
                depthStencil     = new Texture2D(device, depthdesc);
                renderTargetView = new RenderTargetView(device, renderTarget);
                depthStencilView = new DepthStencilView(device, depthStencil);

                // Rendering

                device.OutputMerger.SetTargets(depthStencilView, renderTargetView);
                device.Rasterizer.SetViewports(new Viewport(0, 0, sizeX, sizeY, 0.0f, 1.0f));
                var clearColor = new Color4(1, 1, 1, 0); // Transparent
                if (options.BackgroundBrush != null)
                {
                    var axoColor = options.BackgroundBrush.Color.Color;
                    clearColor = new Color4(axoColor.ScR, axoColor.ScG, axoColor.ScB, axoColor.ScA);
                }
                device.ClearRenderTargetView(renderTargetView, clearColor);
                device.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);

                scene.Attach(device, new PointD2D(sizeX, sizeY));
                scene.Render();
                device.Flush();
                scene.Detach();

                if (sampleCount > 1) // if renderTarget is an MSAA render target, we first have to copy it into a non-MSAA render target before we can copy it to a CPU texture and then hope to save it
                {
                    // create a non-MSAA render target with the same size
                    var renderTarget2Description = new Texture2DDescription
                    {
                        BindFlags         = BindFlags.RenderTarget | BindFlags.ShaderResource,
                        Format            = Format.B8G8R8A8_UNorm_SRgb,
                        Width             = sizeX,
                        Height            = sizeY,
                        MipLevels         = 1,
                        SampleDescription = new SampleDescription(1, 0), // non MSAA
                        Usage             = ResourceUsage.Default,
                        OptionFlags       = ResourceOptionFlags.Shared,
                        CpuAccessFlags    = CpuAccessFlags.None,
                        ArraySize         = 1
                    };

                    renderTarget2 = new Texture2D(device, renderTarget2Description);                               // create non-MSAA render target
                    device.ResolveSubresource(renderTarget, 0, renderTarget2, 0, renderTarget.Description.Format); // copy from MSAA render target to the non-MSAA render target

                    var h = renderTarget;                                                                          // exchange renderTarget with renderTarget2
                    renderTarget  = renderTarget2;
                    renderTarget2 = h;
                }

                // renderTarget is now a non-MSAA renderTarget
                Texture2DExtensions.SaveToStream(renderTarget, options.ImageFormat, options.DestinationDpiResolution, toStream);
            }
            finally
            {
                Disposer.RemoveAndDispose(ref depthStencilView);
                Disposer.RemoveAndDispose(ref renderTargetView);
                Disposer.RemoveAndDispose(ref renderTarget2);
                Disposer.RemoveAndDispose(ref renderTarget);
                Disposer.RemoveAndDispose(ref depthStencil);

                device.ClearState();
                D3D10DeviceFactory.Instance.PassbackDevice(ref device);
                //device.QueryInterface<DeviceDebug>().ReportLiveDeviceObjects(ReportingLevel.Summary)
                // Disposer.RemoveAndDispose(ref device);
                //var activeObjects = SharpDX.Diagnostics.ObjectTracker.FindActiveObjects();
            }
        }
Exemple #7
0
        public override Inline GetInlineItem(string url, out bool inlineItemIsErrorMessage)
        {
            // There are two peculiarities when it comes to creating images from a stream (especially: from a MemoryStream)
            // First peculiarity:
            // The sequence
            //
            // var imageSource = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
            //
            // to create an image can only be used if IsUndoEnabled is set to false in the FlowDocument.
            // This is because the BitmapFrame is not serializable, but the Undo function needs that.
            // Second peculiarity:
            // even then, there is a bug in Wpf when converting the FlowDocument into a FixedDocument:
            // when you use the above sequence to create images from MemoryStreams (tested only for them),
            // all images in the FixedDocument are equal to the first image in the FlowDocument
            // Summary1: we have to use a BitmapImage instead and use the stream to fill it
            // Summary2: It is a good idea anyway to set IsUndoEnabled to false in the FlowDocument, as it speeds up changes of the FlowDocument considerably

            if (url.StartsWith(ImagePretext.GraphRelativePathPretext))
            {
                string graphName = url.Substring(ImagePretext.GraphRelativePathPretext.Length);

                var grp = FindGraphWithUrl(graphName);

                if (grp is Altaxo.Graph.Gdi.GraphDocument graph)
                {
                    var options = new Altaxo.Graph.Gdi.GraphExportOptions()
                    {
                        SourceDpiResolution      = _targetResolution,
                        DestinationDpiResolution = _targetResolution,
                    };

                    using (var stream = new System.IO.MemoryStream())
                    {
                        Altaxo.Graph.Gdi.GraphDocumentExportActions.RenderToStream(graph, stream, options);
                        stream.Seek(0, System.IO.SeekOrigin.Begin);
                        var image = GetImageFromStream(stream);
                        inlineItemIsErrorMessage = false;
                        return(new InlineUIContainer(image));
                    }
                }
                else if (grp is Altaxo.Graph.Graph3D.GraphDocument graph3D)
                {
                    var options = new Altaxo.Graph.Gdi.GraphExportOptions()
                    {
                        SourceDpiResolution      = _targetResolution,
                        DestinationDpiResolution = _targetResolution,
                    };

                    using (var stream = new System.IO.MemoryStream())
                    {
                        if ((0, 0) == Altaxo.Graph.Graph3D.GraphDocumentExportActions.RenderToStream(graph3D, stream, options))
                        {
                            inlineItemIsErrorMessage = true;
                            return(new Run(string.Format("ERROR: NO RENDERER FOR 3D GRAPHS FOUND!")));
                        }

                        stream.Seek(0, System.IO.SeekOrigin.Begin);
                        var image = GetImageFromStream(stream);

                        inlineItemIsErrorMessage = false;
                        return(new InlineUIContainer(image));
                    }
                }
                else
                {
                    inlineItemIsErrorMessage = true;
                    return(new Run(string.Format("ERROR: GRAPH '{0}' NOT FOUND!", graphName)));
                }
            }
            else if (url.StartsWith(ImagePretext.ResourceImagePretext))
            {
                string      name         = url.Substring(ImagePretext.ResourceImagePretext.Length);
                ImageSource bitmapSource = null;
                try
                {
                    bitmapSource = PresentationResourceService.GetBitmapSource(name);
                }
                catch (Exception)
                {
                }

                if (null != bitmapSource)
                {
                    var image = new Image()
                    {
                        Source = bitmapSource
                    };

                    inlineItemIsErrorMessage = false;
                    return(new InlineUIContainer(image));
                }
                else
                {
                    inlineItemIsErrorMessage = true;
                    return(new Run(string.Format("ERROR: RESOURCE '{0}' NOT FOUND!", name)));
                }
            }
            else if (url.StartsWith(ImagePretext.LocalImagePretext))
            {
                string name = url.Substring(ImagePretext.LocalImagePretext.Length);

                if (null != LocalImages && LocalImages.TryGetValue(name, out var img))
                {
                    var   stream = img.GetContentStream();
                    Image image  = GetImageFromStream(stream);

                    inlineItemIsErrorMessage = false;
                    return(new InlineUIContainer(image));
                }
                else
                {
                    inlineItemIsErrorMessage = true;
                    return(new Run(string.Format("ERROR: LOCAL IMAGE '{0}' NOT FOUND!", name)));
                }
            }
            else
            {
                if (string.IsNullOrEmpty(url) || !Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
                {
                    inlineItemIsErrorMessage = false;
                    return(null);
                }
                try
                {
                    var bitmapSource = new BitmapImage(new Uri(url, UriKind.RelativeOrAbsolute));

                    // This is not nice, but we have to validate that our bitmapSource is valid already now, since we may need to resize it immediately,
                    // and we want to provoke the exception if our url was not valid
                    int pixelHeight = bitmapSource.PixelHeight;

                    var image = new Image {
                        Source = bitmapSource
                    };
                    inlineItemIsErrorMessage = false;
                    return(new InlineUIContainer(image));
                }
                catch (Exception ex)
                {
                    inlineItemIsErrorMessage = true;
                    return(new Run(string.Format("ERROR RENDERING '{0}' ({1})", url, ex.Message)));
                }
            }
        }