Exemple #1
0
        /// <summary>
        /// Handles the Click event of the ButtonImagePath control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void ButtonImagePath_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            IGorgonImage image = null;
            var          png   = new GorgonCodecPng();

            try
            {
                if (DialogOpenPng.ShowDialog(this) != DialogResult.OK)
                {
                    return;
                }

                TextImagePath.Text = DialogOpenPng.FileName;
                _sourceTexture?.Texture?.Dispose();
                _outputTexture?.Dispose();
                _sourceTexture = null;
                _outputTexture = null;

                image          = png.LoadFromFile(DialogOpenPng.FileName);
                _sourceTexture = image.ConvertToFormat(BufferFormat.R8G8B8A8_UNorm)
                                 .ToTexture2D(_graphics,
                                              new GorgonTexture2DLoadOptions
                {
                    Name =
                        Path.GetFileNameWithoutExtension(DialogOpenPng.FileName)
                }).GetShaderResourceView();

                _outputTexture = new GorgonTexture2D(_graphics,
                                                     new GorgonTexture2DInfo(_sourceTexture, "Output")
                {
                    Format  = BufferFormat.R8G8B8A8_Typeless,
                    Binding = TextureBinding.ShaderResource | TextureBinding.ReadWriteView
                });

                // Get an SRV for the output texture so we can render it later.
                _outputView = _outputTexture.GetShaderResourceView(BufferFormat.R8G8B8A8_UNorm);

                // Get a UAV for the output.
                _outputUav = _outputTexture.GetReadWriteView(BufferFormat.R32_UInt);

                // Process the newly loaded texture.
                _sobel.Process(_sourceTexture, _outputUav, TrackThickness.Value, TrackThreshold.Value / 100.0f);

                TrackThreshold.Enabled = TrackThickness.Enabled = true;
            }
            catch (Exception ex)
            {
                GorgonDialogs.ErrorBox(this, ex);
                TrackThreshold.Enabled = TrackThickness.Enabled = false;
            }
            finally
            {
                image?.Dispose();
                Cursor.Current = Cursors.Default;
            }
        }
Exemple #2
0
        /// <summary>
        /// Handles the ValueChanged event of the TrackThreshold control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void TrackThreshold_ValueChanged(object sender, EventArgs e)
        {
            if (_sourceTexture == null)
            {
                return;
            }

            Cursor.Current = Cursors.WaitCursor;

            try
            {
                // Unfortunately, because the two interfaces are disconnected, we need to ensure that we're not using a resource on the graphics side
                // when we want access to it on the compute side. This needs to be fixed as it can be a bit on the slow side to constantly do this
                // every frame.
                _sobel.Process(_sourceTexture, _outputUav, TrackThickness.Value, TrackThreshold.Value / 100.0f);

                var png = new GorgonCodecPng();
                using (var tempTexture = new GorgonTexture2D(_graphics, new GorgonTexture2DInfo(_outputTexture)
                {
                    Format = BufferFormat.R8G8B8A8_UNorm
                }))
                {
                    _outputTexture.CopyTo(tempTexture);
                    using (IGorgonImage image = tempTexture.ToImage())
                    {
                        png.SaveToFile(image, @"D:\unpak\uav.png");
                    }
                }
            }
            catch (Exception ex)
            {
                GorgonDialogs.ErrorBox(this, ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }
Exemple #3
0
        /// <summary>Function to retrieve a thumbnail for the content.</summary>
        /// <param name="contentFile">The content file used to retrieve the data to build the thumbnail with.</param>
        /// <param name="fileManager">The content file manager.</param>
        /// <param name="outputFile">The output file for the thumbnail data.</param>
        /// <param name="cancelToken">The token used to cancel the thumbnail generation.</param>
        /// <returns>A <see cref="T:Gorgon.Graphics.Imaging.IGorgonImage"/> containing the thumbnail image data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="contentFile" />, <paramref name="fileManager" /> or the <paramref name="outputFile" /> parameter is <b>null</b>.</exception>
        public async Task <IGorgonImage> GetThumbnailAsync(IContentFile contentFile, IContentFileManager fileManager, FileInfo outputFile, CancellationToken cancelToken)
        {
            if (contentFile == null)
            {
                throw new ArgumentNullException(nameof(contentFile));
            }

            if (fileManager == null)
            {
                throw new ArgumentNullException(nameof(fileManager));
            }

            if (outputFile == null)
            {
                throw new ArgumentNullException(nameof(outputFile));
            }

            // If the content is not a v3 sprite, then leave it.
            if ((!contentFile.Metadata.Attributes.TryGetValue(SpriteContent.CodecAttr, out string codecName)) ||
                (string.IsNullOrWhiteSpace(codecName)) ||
                (!string.Equals(codecName, _defaultCodec.GetType().FullName, StringComparison.OrdinalIgnoreCase)))
            {
                return(null);
            }

            if (!outputFile.Directory.Exists)
            {
                outputFile.Directory.Create();
                outputFile.Directory.Refresh();
            }

            IGorgonImageCodec pngCodec = new GorgonCodecPng();

            (IGorgonImage image, IContentFile imageFile, GorgonSprite sprite) = await Task.Run(() => LoadThumbnailImage(pngCodec, outputFile, contentFile, fileManager, cancelToken));

            if ((image == null) || (cancelToken.IsCancellationRequested))
            {
                return(null);
            }

            // We loaded a cached thumbnail.
            if ((sprite == null) || (imageFile == null))
            {
                return(image);
            }

            // We need to switch back to the main thread here to render the image, otherwise things will break.
            Cursor.Current = Cursors.WaitCursor;

            GorgonTexture2DView spriteTexture = null;
            IGorgonImage        resultImage   = null;

            try
            {
                spriteTexture = GorgonTexture2DView.CreateTexture(GraphicsContext.Graphics, new GorgonTexture2DInfo(imageFile.Path)
                {
                    Width   = image.Width,
                    Height  = image.Height,
                    Format  = image.Format,
                    Binding = TextureBinding.ShaderResource,
                    Usage   = ResourceUsage.Default
                }, image);
                sprite.Texture = spriteTexture;

                resultImage = RenderThumbnail(sprite);

                await Task.Run(() => pngCodec.SaveToFile(resultImage, outputFile.FullName), cancelToken);

                if (cancelToken.IsCancellationRequested)
                {
                    return(null);
                }

                contentFile.Metadata.Attributes[CommonEditorConstants.ThumbnailAttr] = outputFile.Name;
                return(resultImage);
            }
            catch (Exception ex)
            {
                CommonServices.Log.Print($"[ERROR] Cannot create thumbnail for '{contentFile.Path}'", LoggingLevel.Intermediate);
                CommonServices.Log.LogException(ex);
                return(null);
            }
            finally
            {
                image?.Dispose();
                spriteTexture?.Dispose();
                Cursor.Current = Cursors.Default;
            }
        }
Exemple #4
0
        /// <summary>
        /// Function to generate the Gorgon bitmap fonts.
        /// </summary>
        /// <param name="fontFamilies">The list of TrueType font families to use.</param>
        /// <param name="window">The window that contains the loading message.</param>
        private static void GenerateGorgonFonts(IReadOnlyList <Drawing.FontFamily> fontFamilies, FormMain window)
        {
            // Pick a font to use with outlines.
            int fontWithOutlineIndex = GorgonRandom.RandomInt32(1, 5);

            _glowIndex = GorgonRandom.RandomInt32(fontWithOutlineIndex + 1, fontWithOutlineIndex + 5);
            int fontWithGradient = GorgonRandom.RandomInt32(_glowIndex + 1, _glowIndex + 5);
            int fontWithTexture  = GorgonRandom.RandomInt32(fontWithGradient + 1, fontWithGradient + 5).Min(_fontFamilies.Count - 1);

            var pngCodec = new GorgonCodecPng();

            using (IGorgonImage texture = pngCodec.LoadFromFile(Path.Combine(GorgonExample.GetResourcePath(@"Textures\Fonts\").FullName, "Gradient.png")))
            {
                for (int i = 0; i < _fontFamilies.Count; ++i)
                {
                    string fontFamily = _fontFamilies[i];

                    // Use this to determine if the font is avaiable.
                    if (fontFamilies.All(item => !string.Equals(item.Name, fontFamily, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        // Can't locate this one, move on...
                        continue;
                    }

                    bool isExternal =
                        Drawing.FontFamily.Families.All(item => !string.Equals(item.Name, fontFamily, StringComparison.InvariantCultureIgnoreCase));
                    string           fontName;
                    int              outlineSize   = 0;
                    GorgonColor      outlineColor1 = GorgonColor.BlackTransparent;
                    GorgonColor      outlineColor2 = GorgonColor.BlackTransparent;
                    GorgonGlyphBrush brush         = null;

                    if (i == fontWithOutlineIndex)
                    {
                        fontName      = $"{fontFamily} 32px Outlined{(isExternal ? " External TTF" : string.Empty)}";
                        outlineColor1 = GorgonColor.Black;
                        outlineColor2 = GorgonColor.Black;
                        outlineSize   = 3;
                    }
                    else if (i == _glowIndex)
                    {
                        fontName      = $"{fontFamily} 32px Outline as Glow{(isExternal ? " External TTF" : string.Empty)}";
                        outlineColor1 = new GorgonColor(GorgonColor.YellowPure, 1.0f);
                        outlineColor2 = new GorgonColor(GorgonColor.DarkRed, 0.0f);
                        outlineSize   = 16;
                    }
                    else if (i == fontWithGradient)
                    {
                        fontName = $"{fontFamily} 32px Gradient{(isExternal ? " External TTF" : string.Empty)}";
                        brush    = new GorgonGlyphLinearGradientBrush
                        {
                            StartColor = GorgonColor.White,
                            EndColor   = GorgonColor.Black,
                            Angle      = 45.0f
                        };
                    }
                    else if (i == fontWithTexture)
                    {
                        fontName = $"{fontFamily} 32px Textured{(isExternal ? " External TTF" : string.Empty)}";
                        brush    = new GorgonGlyphTextureBrush(texture);
                    }
                    else
                    {
                        fontName = $"{fontFamily} 32px{(isExternal ? " External TTF" : string.Empty)}";
                    }

                    window.UpdateStatus($"Generating Font: {fontFamily}".Ellipses(50));

                    var fontInfo = new GorgonFontInfo(fontFamily,
                                                      30.25f,
                                                      name:
                                                      fontName)
                    {
                        AntiAliasingMode         = FontAntiAliasMode.AntiAlias,
                        OutlineSize              = outlineSize,
                        OutlineColor1            = outlineColor1,
                        OutlineColor2            = outlineColor2,
                        UsePremultipliedTextures = false,
                        Brush = brush
                    };

                    _font.Add(_fontFactory.GetFont(fontInfo));

                    // Texture brushes have to be disposed when we're done with them.
                    var disposableBrush = brush as IDisposable;
                    disposableBrush?.Dispose();
                }
            }
        }
Exemple #5
0
        /// <summary>Function to retrieve a thumbnail for the content.</summary>
        /// <param name="contentFile">The content file used to retrieve the data to build the thumbnail with.</param>
        /// <param name="fileManager">The content file manager.</param>
        /// <param name="outputFile">The output file for the thumbnail data.</param>
        /// <param name="cancelToken">The token used to cancel the thumbnail generation.</param>
        /// <returns>A <see cref="T:Gorgon.Graphics.Imaging.IGorgonImage"/> containing the thumbnail image data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="contentFile" />, <paramref name="fileManager" />, or the <paramref name="outputFile" /> parameter is <b>null</b>.</exception>
        public async Task <IGorgonImage> GetThumbnailAsync(IContentFile contentFile, IContentFileManager fileManager, FileInfo outputFile, CancellationToken cancelToken)
        {
            if (contentFile == null)
            {
                throw new ArgumentNullException(nameof(contentFile));
            }

            if (fileManager == null)
            {
                throw new ArgumentNullException(nameof(fileManager));
            }

            if (outputFile == null)
            {
                throw new ArgumentNullException(nameof(outputFile));
            }

            // If the content is not a DDS image, then leave it.
            if ((!contentFile.Metadata.Attributes.TryGetValue(ImageContent.CodecAttr, out string codecName)) ||
                (string.IsNullOrWhiteSpace(codecName)) ||
                (!string.Equals(codecName, _ddsCodec.GetType().FullName, StringComparison.OrdinalIgnoreCase)))
            {
                return(null);
            }

            if (!outputFile.Directory.Exists)
            {
                outputFile.Directory.Create();
                outputFile.Directory.Refresh();
            }

            IGorgonImageCodec pngCodec = new GorgonCodecPng();

            (IGorgonImage thumbImage, bool needsConversion) = await Task.Run(() => LoadThumbNailImage(pngCodec, outputFile, contentFile, cancelToken));

            if ((thumbImage == null) || (cancelToken.IsCancellationRequested))
            {
                return(null);
            }

            if (!needsConversion)
            {
                return(thumbImage);
            }

            // We need to switch back to the main thread here to render the image, otherwise things will break.
            Cursor.Current = Cursors.WaitCursor;

            try
            {
                const float maxSize = 256;
                float       scale   = (maxSize / thumbImage.Width).Min(maxSize / thumbImage.Height);
                RenderThumbnail(ref thumbImage, scale);

                if (cancelToken.IsCancellationRequested)
                {
                    return(null);
                }

                // We're done on the main thread, we can switch to another thread to write the image.
                Cursor.Current = Cursors.Default;

                await Task.Run(() => pngCodec.SaveToFile(thumbImage, outputFile.FullName), cancelToken);

                if (cancelToken.IsCancellationRequested)
                {
                    return(null);
                }

                contentFile.Metadata.Attributes[CommonEditorConstants.ThumbnailAttr] = outputFile.Name;
                return(thumbImage);
            }
            catch (Exception ex)
            {
                CommonServices.Log.Print($"[ERROR] Cannot create thumbnail for '{contentFile.Path}'", LoggingLevel.Intermediate);
                CommonServices.Log.LogException(ex);
                return(null);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }
Exemple #6
0
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Cursor.Current = Cursors.WaitCursor;

            try
            {
                GorgonExample.ResourceBaseDirectory = new DirectoryInfo(Settings.Default.ResourceLocation);

                // Load the custom codec.
                if (!LoadCodec())
                {
                    GorgonDialogs.ErrorBox(this, "Unable to load the image codec plug in.");
                    GorgonApplication.Quit();
                    return;
                }


                // Set up the graphics interface.
                // Find out which devices we have installed in the system.
                IReadOnlyList <IGorgonVideoAdapterInfo> deviceList = GorgonGraphics.EnumerateAdapters();

                if (deviceList.Count == 0)
                {
                    GorgonDialogs.ErrorBox(this, "There are no suitable video adapters available in the system. This example is unable to continue and will now exit.");
                    GorgonApplication.Quit();
                    return;
                }

                _graphics = new GorgonGraphics(deviceList[0]);

                _swap = new GorgonSwapChain(_graphics,
                                            this,
                                            new GorgonSwapChainInfo("Codec PlugIn SwapChain")
                {
                    Width  = ClientSize.Width,
                    Height = ClientSize.Height,
                    Format = BufferFormat.R8G8B8A8_UNorm
                });

                _graphics.SetRenderTarget(_swap.RenderTargetView);

                // Load the image to use as a texture.
                IGorgonImageCodec png = new GorgonCodecPng();
                _image = png.LoadFromFile(Path.Combine(GorgonExample.GetResourcePath(@"Textures\CodecPlugIn\").FullName, "SourceTexture.png"));

                GorgonExample.LoadResources(_graphics);

                ConvertImage();

                GorgonApplication.IdleMethod = Idle;
            }
            catch (Exception ex)
            {
                GorgonExample.HandleException(ex);
                GorgonApplication.Quit();
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }