Skip to content

Commit

Permalink
#508 Added support for SVG images
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriyKulagin committed Mar 18, 2022
1 parent 14635b3 commit 8ae9b8b
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 8 deletions.
5 changes: 5 additions & 0 deletions src/Libraries/Nop.Core/MimeTypes.cs
Expand Up @@ -92,6 +92,11 @@ public static class MimeTypes
/// </summary>
public static string ImageWebp => "image/webp";

/// <summary>
/// Type
/// </summary>
public static string ImageSvg => "image/svg+xml";

#endregion

#region text/*
Expand Down
14 changes: 13 additions & 1 deletion src/Libraries/Nop.Services/Common/PdfService.cs
Expand Up @@ -1191,7 +1191,19 @@ protected virtual async Task PrintHeaderAsync(PdfSettings pdfSettingsByStore, La
if (logoExists)
{
var logoFilePath = await _pictureService.GetThumbLocalPathAsync(logoPicture, 0, false);
var logo = Image.GetInstance(logoFilePath);
Image logo;

if (logoPicture.MimeType == MimeTypes.ImageSvg)
{
//we must first convert the SVG to PNG to show the image in the PDF document
var picturePng = await _pictureService.ConvertSvgToPngAsync(logoFilePath);
logo = Image.GetInstance(picturePng);
}
else
{
logo = Image.GetInstance(logoFilePath);
}

logo.Alignment = GetAlignment(lang, true);
logo.ScaleToFit(65f, 65f);

Expand Down
8 changes: 8 additions & 0 deletions src/Libraries/Nop.Services/Media/IPictureService.cs
Expand Up @@ -258,5 +258,13 @@ public partial interface IPictureService
/// The task result contains the picture binary
/// </returns>
Task<PictureBinary> GetPictureBinaryByPictureIdAsync(int pictureId);

/// <summary>
/// Convert image from SVG format to PNG
/// </summary>
/// <param name="filePath">SVG file path</param>
/// <returns>A task that represents the asynchronous operation
/// The task result contains the byte array</returns>
Task<byte[]> ConvertSvgToPngAsync(string filePath);
}
}
73 changes: 68 additions & 5 deletions src/Libraries/Nop.Services/Media/PictureService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -14,6 +15,8 @@
using Nop.Services.Configuration;
using Nop.Services.Seo;
using SkiaSharp;
using Svg;
using Svg.Skia;

namespace Nop.Services.Media
{
Expand Down Expand Up @@ -430,6 +433,9 @@ public virtual Task<string> GetFileExtensionFromMimeTypeAsync(string mimeType)
case "x-icon":
lastPart = "ico";
break;
case "svg+xml":
lastPart = "svg";
break;
default:
break;
}
Expand Down Expand Up @@ -638,9 +644,22 @@ public virtual async Task<string> GetPictureSeNameAsync(string name)
{
try
{
using var image = SKBitmap.Decode(pictureBinary);
var format = GetImageFormatByMimeType(picture.MimeType);
pictureBinary = ImageResize(image, format, targetSize);
if (picture.MimeType == MimeTypes.ImageSvg)
{
using var memStream = new MemoryStream(pictureBinary);
var svgDocument = SvgDocument.Open<SvgDocument>(memStream);
svgDocument.Height = targetSize;
svgDocument.Width = targetSize;
using var stream = new MemoryStream();
svgDocument.Write(stream);
pictureBinary = stream.ToArray();
}
else
{
using var image = SKBitmap.Decode(pictureBinary);
var format = GetImageFormatByMimeType(picture.MimeType);
pictureBinary = ImageResize(image, format, targetSize);
}
}
catch
{
Expand Down Expand Up @@ -679,6 +698,46 @@ public virtual async Task<string> GetThumbLocalPathAsync(Picture picture, int ta

#endregion

#region Convertation methods

/// <summary>
/// Convert image from SVG format to PNG
/// </summary>
/// <param name="filePath">SVG file path</param>
/// <returns>A task that represents the asynchronous operation
/// The task result contains the byte array</returns>
public virtual Task<byte[]> ConvertSvgToPngAsync(string filePath)
{
try
{
using var svg = new SKSvg();
svg.Load(filePath);

using var bitmap = new SKBitmap((int)svg.Picture.CullRect.Width, (int)svg.Picture.CullRect.Height);
var canvas = new SKCanvas(bitmap);
canvas.DrawPicture(svg.Picture);
canvas.Flush();
canvas.Save();

using var image = SKImage.FromBitmap(bitmap);
using var data = image.Encode(SKEncodedImageFormat.Png, 100);

// save the data to a stream
using var memStream = new MemoryStream();
data.SaveTo(memStream);
memStream.Seek(0, SeekOrigin.Begin);

return Task.FromResult(memStream.ToArray());
}
catch
{
}

return null;
}

#endregion

#region CRUD methods

/// <summary>
Expand Down Expand Up @@ -833,7 +892,8 @@ public virtual async Task<Picture> InsertPictureAsync(IFormFile formFile, string
".pjp",
".png",
".tiff",
".tif"
".tif",
".svg"
} as IReadOnlyCollection<string>;

var fileName = formFile.FileName;
Expand All @@ -855,7 +915,7 @@ public virtual async Task<Picture> InsertPictureAsync(IFormFile formFile, string
//contentType is not always available
//that's why we manually update it here
//http://www.sfsu.edu/training/mimetype.htm
if (string.IsNullOrEmpty(contentType))
if (string.IsNullOrEmpty(contentType) || contentType == MimeTypes.ImageSvg)
{
switch (fileExtension)
{
Expand All @@ -879,6 +939,9 @@ public virtual async Task<Picture> InsertPictureAsync(IFormFile formFile, string
case ".png":
contentType = MimeTypes.ImagePng;
break;
case ".svg":
contentType = MimeTypes.ImageSvg;
break;
case ".tiff":
case ".tif":
contentType = MimeTypes.ImageTiff;
Expand Down
Expand Up @@ -113,7 +113,7 @@ protected virtual string GetFileType(string fileExtension)
var fileType = "file";

fileExtension = fileExtension.ToLowerInvariant();
if (fileExtension == ".jpg" || fileExtension == ".jpeg" || fileExtension == ".png" || fileExtension == ".gif" || fileExtension == ".webp")
if (fileExtension == ".jpg" || fileExtension == ".jpeg" || fileExtension == ".png" || fileExtension == ".gif" || fileExtension == ".webp" || fileExtension == ".svg")
fileType = "image";

if (fileExtension == ".swf" || fileExtension == ".flv")
Expand Down
1 change: 1 addition & 0 deletions src/Libraries/Nop.Services/Nop.Services.csproj
Expand Up @@ -21,6 +21,7 @@
<PackageReference Include="MaxMind.GeoIP2" Version="4.1.0" />
<PackageReference Include="SkiaSharp" Version="2.80.3" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.80.3" />
<PackageReference Include="Svg.Skia" Version="0.5.10" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.15" />
<PackageReference Include="System.ServiceModel.Http" Version="4.9.0" />
</ItemGroup>
Expand Down
Expand Up @@ -87,7 +87,7 @@
template: "@(clientId)-qq-template",
multiple: false,
validation: {
allowedExtensions: [ "bmp", "gif", "jpeg", "jpg", "jpe", "jfif", "pjpeg", "pjp", "png", "tiff", "tif", "webp"]
allowedExtensions: [ "bmp", "gif", "jpeg", "jpg", "jpe", "jfif", "pjpeg", "pjp", "png", "tiff", "tif", "webp", "svg"]
}
}).on("complete", function(event, id, name, responseJSON, xhr) {
if (responseJSON.success) {
Expand Down

0 comments on commit 8ae9b8b

Please sign in to comment.