Files
Common-VS2019/SacsStandardBase/Base/Utils/ImageUtils.cs
T
2024-08-20 17:51:51 +01:00

175 lines
6.0 KiB
C#

using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Helpers;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Sarand.Net.Standard.Base.Utils
{
//=======================================================================
// Image handling methods utilising SixLabors ImageSharp package.
//=======================================================================
public static class ImageUtils
{
//-------------------------------------------------------------------
private static readonly String className = typeof(ImageUtils).ToString();
//-------------------------------------------------------------------
public class ImageConfig
{
public byte[] ImageData { get; set; }
public string ImageFormatName;
public string DefaultMimeType;
public Sacs.MimeType MimeType;
public bool ValidImage { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
//-------------------------------------------------------------------
public static bool IsSvg(byte[] imageData)
{
try
{
if (!imageData.Contains((byte)'<')) return false;
String imageText = Encoding.UTF8.GetString(imageData);
if (!imageText.ContainsCI("<svg")) return false;
if (!imageText.ContainsCI(" xmlns=\"http://www.w3.org/2000/svg\"")) return false;
return true;
}
catch (Exception) { }
return false;
}
//-------------------------------------------------------------------
/// <summary>
/// Convert the data stream to an image and extract width and height.
/// </summary>
/// <param name="imageData"></param>
/// <returns>Flag to indicate whether interpretation of image data succeeded.</returns>
public static ImageConfig VerifyImageData(byte[] imageData)
{
ImageConfig imageConfig = new ImageConfig();
imageConfig.ImageData = imageData;
try
{
IImageFormat imageFormat = null;
using (var image = LoadImage(imageData, out imageFormat))
{
if (image == null) return imageConfig;
imageConfig.ImageFormatName = imageFormat.Name;
imageConfig.DefaultMimeType = imageFormat.DefaultMimeType;
imageConfig.MimeType = EnumUtil.ParseEnum(imageConfig.ImageFormatName, Sacs.MimeType.Unknown);
imageConfig.Width = image.Width;
imageConfig.Height = image.Height;
}
imageConfig.ValidImage = true;
}
catch (Exception exc)
{
SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}");
}
return imageConfig;
}
//-------------------------------------------------------------------
/// <summary>
/// Convert the SVG data stream to an image and extract width and height.
/// </summary>
/// <param name="imageData"></param>
/// <returns>Flag to indicate whether interpretation of image data succeeded.</returns>
public static ImageConfig VerifySvgImageData(byte[] imageData)
{
ImageConfig imageConfig = new ImageConfig();
imageConfig.ImageData = imageData;
imageConfig.ImageFormatName = "svg";
imageConfig.DefaultMimeType = "svg";
imageConfig.MimeType = EnumUtil.ParseEnum(imageConfig.ImageFormatName, Sacs.MimeType.Unknown);
imageConfig.Width = 0;
imageConfig.Height = 0;
imageConfig.ValidImage = true;
return imageConfig;
}
//-------------------------------------------------------------------
// Load from byte array.
/// <summary>Convert the data stream to an image.</summary>
public static SixLabors.ImageSharp.Image LoadImage(byte[] imageData)
{
var image = Image.Load<Rgba32>(imageData);
return image;
}
/// <summary>
/// Convert the data stream to an image.
/// <para>Identify the image's format on load.</para>
/// </summary>
public static SixLabors.ImageSharp.Image LoadImage(byte[] imageData, out IImageFormat format)
{
var image = Image.Load<Rgba32>(imageData);
format = Image.DetectFormat(imageData);
return image;
}
//-------------------------------------------------------------------
// Convert to byte array.
/// <summary>Convert the data stream to an image.</summary>
public static Byte[] GetImageData(this SixLabors.ImageSharp.Image image, IImageFormat imageFormat)
{
using (MemoryStream ms = new MemoryStream())
{
var imageEncoder = image.Configuration.ImageFormatsManager.GetEncoder(imageFormat);
image.Save(ms, imageEncoder);
return ms.ToArray();
}
}
//-------------------------------------------------------------------
/// <summary>
/// Resize the image with the specified limits, if required.
/// </summary>
/// <param name="config">Image data</param>
/// <param name="widthMax"></param>
/// <param name="heightMax"></param>
/// <returns>Flag to indicate whether operation was successful.</returns>
public static bool ConstrainImage(ImageConfig config, ushort widthMax, ushort heightMax)
{
if (config.Width == 0 || config.Height == 0) return true;
if (widthMax < 1 || heightMax < 1) return false;
if (config.Width <= widthMax && config.Height <= heightMax) return true;
config.ValidImage = false;
try
{
// Resize the image.
IImageFormat imageFormat = null;
using (var image = LoadImage(config.ImageData, out imageFormat))
{
double resizeProportion = Math.Min(widthMax / (double)image.Width, heightMax / (double)image.Height);
image.Mutate(img => img.Resize((int)(image.Width * resizeProportion), (int)(image.Height * resizeProportion)));
config.ImageData = image.GetImageData(imageFormat);
config.Width = image.Width;
config.Height = image.Height;
config.ValidImage = true;
}
}
catch (Exception exc)
{
SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}");
}
return config.ValidImage;
}
//-------------------------------------------------------------------
}
//=======================================================================
}