简体   繁体   中英

server-side graphics generation in .net/c#

Is there a "correct" way in .net (MVC/c#, etc) to dynamically generate images in a way like this site does: http://www.fodey.com/generators/newspaper/snippet.asp And/or, are there third party toolkits to help with such things?

I'm aware of the low level graphics api's, but would be curious how to handle more advanced things like font layout, pagination, etc. in a way that doesn't require a ton of manual coding.

There are a lot of imaging libraries out there. IMO there is no "best practice" way ("correct","famous" library). There is the "standard" approach where you need to code everything by your self (as you said), using nothing else but the GDI+ (System.Drawing) library or you can have a look at:

Alas, sometimes the best and the quickest solution is still writing your own code - depending on the result you want to achieve, the time you will spend learning the API of the third party library, you will probably create the solution by yourself using the framework build-in library.

It would be simple to write a server side library which references a few WPF assemblies (PresentationFramework, PresentationCore, WindowsBase), then overlay and graphics or text on top of a background image, similar to the following:

    public ImageSource ApplyTextToBitmapSource(ImageSource backgroundImageSource, string text, Point location, FontFamily font, double fontSize, Brush foreground)
    {
        TextBlock tb = new TextBlock();
        tb.Text = text;
        tb.FontFamily = font;
        tb.FontSize = fontSize;
        tb.Foreground = foreground;
        tb.Margin = new Thickness(location.X, location.Y, 0.0d, 0.0d);

        Image image = new Image();
        image.Stretch = Stretch.Uniform;
        image.Source = backgroundImageSource;

        Grid container = new Grid();
        container.Width = backgroundImageSource.Width;
        container.Height = backgroundImageSource.Height;
        container.Background = new ImageBrush(backgroundImageSource);
        container.Children.Add(tb);

        return RenderElementToBitmap(container, new Size(backgroundImageSource.Width, backgroundImageSource.Height));
    }

    private ImageSource RenderElementToBitmap(FrameworkElement element, Size maxSize)
    {
        element.Measure(maxSize);
        element.Arrange(new Rect(element.DesiredSize));

        RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap((int)Math.Ceiling(element.ActualWidth),
            (int)Math.Ceiling(element.ActualHeight), 96, 96, PixelFormats.Pbgra32);

        DrawingVisual visual = new DrawingVisual();
        using (DrawingContext ctx = visual.RenderOpen())
        {
            VisualBrush brush = new VisualBrush(element);
            Rect bounds = VisualTreeHelper.GetDescendantBounds(element);
            Rect targetRect = new Rect(0.0d, 0.0d, bounds.Width, bounds.Height);
            ctx.DrawRectangle(brush, null, targetRect);
        }
        renderTargetBitmap.Render(visual);
        return renderTargetBitmap;
    }

The calls would look similar to the following:

        FontFamily font = new FontFamily("Arial Bold");
        ImageSource backgroundImageSource = new BitmapImage(new Uri("X:\\Dev\\WPF_Poster.png", UriKind.Absolute));
        ImageSource imageSource = ApplyTextToBitmapSource(backgroundImageSource, "Overlayed Text", new Point(70.0d, 70.0d), font, 31.0d, Brushes.Blue);

Hope this helps. Let me know if you would want any further info.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM