.NET Core ImageSharp масштабирование изображения - PullRequest
1 голос
/ 13 марта 2019

У меня есть два изображения, одно в качестве фона и одно с подписью. Я хочу иметь возможность уменьшить / увеличить масштаб подписи в зависимости от коэффициента масштабирования, но в пределах высоты / ширины фона. Я пробовал AffineTransformBuilder.AppendScale без какого-либо успеха, поэтому вместо этого я попытался масштабировать подпись с изменением размера. Как я могу масштабировать изображение подписи в пределах фонового изображения?

Результаты изображения

Ожидаемый результат expected image

Фактический результат с изменением размера actual image

код

public class ImageConverter 
{

    public byte[] GetPngImage(byte[] plots) 
    {
        var desiredWidth = 250;
        var desiredHeight = 250;

        var Rgba32 backgroundColor = Rgba32.White;
        var Rgba32 foregroundColor = Rgba32.Black;

        var plottedLines = GetPlottedLines(plots);

        var minX = lines.Min(p => p.Start.X > p.End.X ? p.Start.X : p.End.X);
        var maxX = lines.Max(p => p.Start.X > p.End.X ? p.Start.X : p.End.X);
        var minY = lines.Min(p => p.Start.Y > p.End.Y ? p.Start.Y : p.End.Y);
        var maxY = lines.Max(p => p.Start.Y > p.End.Y ? p.Start.Y : p.End.Y);

        var width = maxX - minX;
        var height = maxY - minY;

        var scaleFactor = CalculateScaleFactor(width, height, desiredWidth, desiredHeight);

            using (var canvas = new Image<Rgba32>(desiredWidth, desiredHeight))
            using(var signature = new Image<Rgba32>(width, height))
            {
                signature.Mutate(ctx =>
                {
                    var pen = new Pen<Rgba32>(foregroundColor, 1);

                    foreach (var line in plottedLines)
                    {
                        ctx.DrawLines(pen, new PointF(line.Start.X - minX, line.Start.Y - minY),
                            new PointF(line.End.X - minX, line.End.Y - minY));
                    }

                    ctx.Resize(new ResizeOptions
                    {
                        Size = new Size(desiredWidth, desiredHeight),
                        Mode = ResizeMode.BoxPad,
                    });

                    //var transformX = ((desiredWidth / 2f) - (width * scaleFactor) / 2f) < 0f ? 0f : ((desiredWidth / 2f) - (width * scaleFactor) / 2f);

                    //var transformY = ((desiredHeight / 2f) - (height * scaleFactor) / 2f) < 0f ? 0f : ((desiredHeight / 2f) - (height * scaleFactor) / 2f);

                    //var transformBuilder = new AffineTransformBuilder();
                   //transformBuilder.AppendTranslation(new PointF(transformX, transformY));
                   //transformBuilder.AppendScale(scaleFactor);

                   //ctx.Transform(transformBuilder);

                   //var pen = new Pen<Rgba32>(foregroundColor, 1);

                   //foreach (var line in plottedLines)
                   //{
                   //ctx.DrawLines(pen, new PointF(line.Start.X - minX, line.Start.Y - minY), new PointF(line.End.X - minX, line.End.Y - minY));
                   //}
                });

                canvas.Mutate(ctx =>
                {
                    ctx.Fill(new SolidBrush<Rgba32>(backgroundColor), new RectangleF(0, 0, desiredWidth, desiredHeight));
                    ctx.DrawImage(signature, new Point(0, 0), 1);
                });

                using (var ms = new MemoryStream())
                {
                    canvas.Save(ms, new PngEncoder());
                    return ms.ToArray();
                }
            }
    }

   private List<Line> GetPlottedLines(byte[] plotChunk)
    {
        var plotString = Encoding.Default.GetString(plotChunk);
        var lines = plotString.Split(new[] {"|"}, StringSplitOptions.RemoveEmptyEntries);

        return lines.Select(line =>
                line.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries))
            .Select(points => new Line(
                new Point(Convert.ToInt32(points[0]), Convert.ToInt32(points[1])),
                new Point(Convert.ToInt32(points[2]), Convert.ToInt32(points[3]))))
            .ToList();
    }

    private float CalculateScaleFactor(float currentImageWidthInPixels, float currentImageHeightInPixels,
        int desiredWidthInPixels, int desiredHeightInPixels)
    {
        var scaleFactorWidth = desiredWidthInPixels / currentImageWidthInPixels;
        var scaleFactorHeight = desiredHeightInPixels / currentImageHeightInPixels;

        var scaleFactor = scaleFactorWidth < scaleFactorHeight ? scaleFactorWidth : scaleFactorHeight;

        return scaleFactor == 0.0 ? 1.0f : scaleFactor;
    }

    private class Line
    {
        internal Point Start { get; }
        internal Point End { get; }

        public Line(Point start, Point end)
        {
            Start = start;
            End = end;
        }
    }
}
...