/
DefaultImageProcessor.cs
144 lines (121 loc) · 4.52 KB
/
DefaultImageProcessor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.IO;
namespace Serenity.Web;
/// <summary>
/// Default implementation for the <see cref="IImageProcessor"/>
/// </summary>
public class DefaultImageProcessor : IImageProcessor
{
/// <inheritdoc/>
public (int width, int height) GetImageSize(object imageObj)
{
if (imageObj == null)
throw new ArgumentNullException(nameof(imageObj));
if (imageObj is not Image image)
throw new ArgumentOutOfRangeException(nameof(imageObj));
return (image.Width, image.Height);
}
/// <inheritdoc/>
public object Load(Stream source, out ImageFormatInfo formatInfo)
{
formatInfo = null;
var image = Image.Load(source, out var format);
try
{
formatInfo = new()
{
MimeType = format.DefaultMimeType,
FileExtensions = format.FileExtensions
};
return image;
}
catch
{
image.Dispose();
throw;
}
}
/// <inheritdoc/>
public void Save(object imageObj, Stream target, string mimeType, ImageEncoderParams encoderParams)
{
if (imageObj == null)
throw new ArgumentNullException(nameof(imageObj));
if (imageObj is not Image image)
throw new ArgumentOutOfRangeException(nameof(imageObj));
if (target is null)
throw new ArgumentNullException(nameof(target));
if (mimeType is null)
throw new ArgumentNullException(nameof(mimeType));
IImageEncoder encoder = mimeType switch
{
"image/jpeg" => new JpegEncoder() { Quality = ((encoderParams?.Quality ?? 0) == 0) ? null : encoderParams.Quality },
"image/png" => new PngEncoder(),
"image/gif" => new GifEncoder(),
"image/webp" => new WebpEncoder(),
_ => throw new ArgumentOutOfRangeException(nameof(mimeType)),
};
image.Save(target, encoder);
}
/// <inheritdoc/>
public object Scale(object imageObj, int scaleWidth, int scaleHeight, ImageScaleMode mode, string backgroundColor, bool inplace)
{
if (imageObj == null)
throw new ArgumentNullException(nameof(imageObj));
if (imageObj is not Image image)
throw new ArgumentOutOfRangeException(nameof(imageObj));
int imageWidth = image.Width;
int imageHeight = image.Height;
Color padColor = string.IsNullOrEmpty(backgroundColor) ? Color.Black : Color.Parse(backgroundColor);
// if image or thumb width and height is zero, return an empty image
if (imageWidth <= 0 || imageHeight <= 0 || (scaleWidth <= 0 && scaleHeight <= 0))
return GenerateEmptyBitmap(imageWidth, imageHeight, padColor);
// if thumb width is zero, thumb height is not zero
// so calculate width by aspect ratio, do similar
// if thumb height is zero. for both states, aspect
// ratio of source and thumb will be same
if (scaleWidth == 0)
{
scaleWidth = Convert.ToInt32(imageWidth * scaleHeight / ((double)imageHeight));
mode = ImageScaleMode.StretchToFit;
}
else if (scaleHeight == 0)
{
scaleHeight = Convert.ToInt32(imageHeight * scaleWidth / ((double)imageWidth));
mode = ImageScaleMode.StretchToFit;
}
var resizeMode = mode switch
{
ImageScaleMode.PreserveRatioNoFill => ResizeMode.Max,
ImageScaleMode.PreserveRatioWithFill => ResizeMode.Pad,
ImageScaleMode.CropSourceImage => ResizeMode.Crop,
_ => ResizeMode.Stretch,
};
void operation(IImageProcessingContext x)
{
x.Resize(new ResizeOptions
{
Mode = resizeMode,
Size = new Size(scaleWidth, scaleHeight),
PremultiplyAlpha = false,
PadColor = padColor
});
}
if (inplace)
{
image.Mutate(operation);
return image;
}
return image.Clone(operation);
}
private Image GenerateEmptyBitmap(int width, int height, Color color)
{
return new Image<Rgb24>(width, height, color);
}
}