Add WebP support for media
This commit is contained in:
parent
9bc44500fc
commit
516465ad1a
7 changed files with 33 additions and 13 deletions
|
|
@ -9,6 +9,7 @@ using ZiggyCreatures.Caching.Fusion;
|
|||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||
using SixLabors.ImageSharp.Formats.Webp;
|
||||
using LANCommander.SDK.Enums;
|
||||
using LANCommander.SDK.Extensions;
|
||||
using LANCommander.Server.Services.Extensions;
|
||||
|
|
@ -214,7 +215,7 @@ namespace LANCommander.Server.Services
|
|||
|
||||
image.Mutate(context => context.Resize(resizeOptions));
|
||||
|
||||
if (media.Type.ValueIsIn(MediaType.Icon, MediaType.Logo, MediaType.PageImage) && media.MimeType == MediaTypeNames.Image.Png && HasTransparentPixels(image))
|
||||
if (media.Type.ValueIsIn(MediaType.Icon, MediaType.Logo, MediaType.PageImage) && (media.MimeType == MediaTypeNames.Image.Png || media.MimeType == MediaTypeNames.Image.Webp) && HasTransparentPixels(image))
|
||||
{
|
||||
await image.SaveAsPngAsync(destination);
|
||||
}
|
||||
|
|
@ -371,8 +372,9 @@ namespace LANCommander.Server.Services
|
|||
var mime = media.MimeType?.ToLowerInvariant();
|
||||
var isPng = mime == "image/png";
|
||||
var isJpeg = mime == "image/jpeg" || mime == "image/jpg";
|
||||
var isWebp = mime == "image/webp";
|
||||
|
||||
if (!isPng && !isJpeg)
|
||||
if (!isPng && !isJpeg && !isWebp)
|
||||
continue;
|
||||
|
||||
int width;
|
||||
|
|
@ -391,7 +393,7 @@ namespace LANCommander.Server.Services
|
|||
|
||||
var oversized = options.Downscale && Math.Max(width, height) > options.MaxLongEdge;
|
||||
var willConvert = isPng && options.ConvertPngToJpeg && media.Type != MediaType.Logo && media.Type != MediaType.Icon;
|
||||
var willRecompress = isJpeg && options.RecompressJpeg;
|
||||
var willRecompress = (isJpeg && options.RecompressJpeg) || (isWebp && options.RecompressWebp);
|
||||
|
||||
if (!willConvert && !oversized && !willRecompress)
|
||||
continue;
|
||||
|
|
@ -438,8 +440,9 @@ namespace LANCommander.Server.Services
|
|||
var mime = media.MimeType?.ToLowerInvariant();
|
||||
var isPng = mime == "image/png";
|
||||
var isJpeg = mime == "image/jpeg" || mime == "image/jpg";
|
||||
var isWebp = mime == "image/webp";
|
||||
|
||||
if (!isPng && !isJpeg)
|
||||
if (!isPng && !isJpeg && !isWebp)
|
||||
return result;
|
||||
|
||||
result.BeforeBytes = new FileInfo(path).Length;
|
||||
|
|
@ -479,14 +482,17 @@ namespace LANCommander.Server.Services
|
|||
}
|
||||
|
||||
var reencodeJpeg = isJpeg && (options.RecompressJpeg || changed);
|
||||
var reencodeWebp = isWebp && (options.RecompressWebp || changed);
|
||||
|
||||
if (!convertToJpeg && !reencodeJpeg && !(isPng && changed))
|
||||
if (!convertToJpeg && !reencodeJpeg && !reencodeWebp && !(isPng && changed))
|
||||
return result;
|
||||
|
||||
var tempPath = path + ".optimizing";
|
||||
|
||||
if (convertToJpeg || isJpeg)
|
||||
await image.SaveAsJpegAsync(tempPath, new JpegEncoder { Quality = options.JpegQuality });
|
||||
else if (isWebp)
|
||||
await image.SaveAsWebpAsync(tempPath, new WebpEncoder { Quality = options.WebpQuality });
|
||||
else
|
||||
await image.SaveAsPngAsync(tempPath);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ namespace LANCommander.Server.Services.Models
|
|||
public bool Downscale { get; set; } = true;
|
||||
public int MaxLongEdge { get; set; } = 3840;
|
||||
public bool RecompressJpeg { get; set; } = false;
|
||||
public bool RecompressWebp { get; set; } = false;
|
||||
public int WebpQuality { get; set; } = 80;
|
||||
public bool StripMetadata { get; set; } = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
@inject IOptions<Settings.Settings> Settings
|
||||
@inject IMessageService MessageService
|
||||
|
||||
<InputFile id="@("AvatarUpload")" OnChange="(e) => UploadAvatar(e)" hidden accept=".jpg,jpeg,.png" />
|
||||
<InputFile id="@("AvatarUpload")" OnChange="(e) => UploadAvatar(e)" hidden accept=".jpg,jpeg,.png,.webp" />
|
||||
|
||||
<label for="AvatarUpload" style="cursor: pointer;">
|
||||
@if (String.IsNullOrWhiteSpace(AvatarUrl))
|
||||
|
|
@ -38,7 +38,8 @@
|
|||
string[] ValidMimeTypes = new string[]
|
||||
{
|
||||
"image/png",
|
||||
"image/jpeg"
|
||||
"image/jpeg",
|
||||
"image/webp"
|
||||
};
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
<div class="game-detail-preview__media-overlay game-detail-preview__media-overlay--hero">
|
||||
<div class="game-detail-preview__media-overlay-actions">
|
||||
@{ var bgInputId = "bg-upload-" + Guid.NewGuid(); }
|
||||
<InputFile id="@bgInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Background)" hidden accept=".jpg,.jpeg,.png,.gif" />
|
||||
<InputFile id="@bgInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Background)" hidden accept=".jpg,.jpeg,.png,.gif,.webp" />
|
||||
<label class="game-detail-preview__overlay-btn" for="@bgInputId" title="Upload Background">
|
||||
<Icon Type="@IconType.Outline.Upload" />
|
||||
</label>
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
<div class="game-detail-preview__media-overlay game-detail-preview__media-overlay--logo">
|
||||
<div class="game-detail-preview__media-overlay-actions">
|
||||
@{ var logoInputId = "logo-upload-" + Guid.NewGuid(); }
|
||||
<InputFile id="@logoInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Logo)" hidden accept=".jpg,.jpeg,.png,.gif" />
|
||||
<InputFile id="@logoInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Logo)" hidden accept=".jpg,.jpeg,.png,.gif,.webp" />
|
||||
<label class="game-detail-preview__overlay-btn" for="@logoInputId" title="Upload Logo">
|
||||
<Icon Type="@IconType.Outline.Upload" />
|
||||
</label>
|
||||
|
|
@ -106,7 +106,7 @@
|
|||
<div class="game-detail-preview__media-section-header">
|
||||
<span class="game-detail-preview__media-section-title">Media</span>
|
||||
<div class="game-detail-preview__media-section-actions">
|
||||
<InputFile id="@_ssInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Screenshot)" hidden accept=".jpg,.jpeg,.png,.gif" multiple />
|
||||
<InputFile id="@_ssInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Screenshot)" hidden accept=".jpg,.jpeg,.png,.gif,.webp" multiple />
|
||||
<InputFile id="@_vidInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Video)" hidden accept=".mp4,.webm,.mkv" multiple />
|
||||
|
||||
<Dropdown>
|
||||
|
|
@ -208,7 +208,7 @@
|
|||
<div class="game-detail-preview__media-overlay game-detail-preview__media-overlay--cover">
|
||||
<div class="game-detail-preview__media-overlay-actions">
|
||||
@{ var coverInputId = "cover-upload-" + Guid.NewGuid(); }
|
||||
<InputFile id="@coverInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Cover)" hidden accept=".jpg,.jpeg,.png,.gif,.apng,.mp4,.webm,.mkv" />
|
||||
<InputFile id="@coverInputId" OnChange="(e) => UploadMediaByType(e, MediaType.Cover)" hidden accept=".jpg,.jpeg,.png,.gif,.webp,.apng,.mp4,.webm,.mkv" />
|
||||
<label class="game-detail-preview__overlay-btn" for="@coverInputId" title="Upload Cover">
|
||||
<Icon Type="@IconType.Outline.Upload" />
|
||||
</label>
|
||||
|
|
@ -318,6 +318,7 @@
|
|||
MediaTypeNames.Image.Png,
|
||||
MediaTypeNames.Image.Jpeg,
|
||||
MediaTypeNames.Image.Gif,
|
||||
MediaTypeNames.Image.Webp,
|
||||
"image/apng",
|
||||
];
|
||||
|
||||
|
|
@ -331,6 +332,7 @@
|
|||
MediaTypeNames.Image.Png,
|
||||
MediaTypeNames.Image.Jpeg,
|
||||
MediaTypeNames.Image.Gif,
|
||||
MediaTypeNames.Image.Webp,
|
||||
"image/apng",
|
||||
"video/mp4",
|
||||
"video/webm",
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
@{
|
||||
var fileInputId = Guid.NewGuid();
|
||||
}
|
||||
<InputFile id="@fileInputId" OnChange="(e) => UploadMedia(e, row)" hidden accept=".jpg,.jpeg,.png,.gif,.pdf,.ico,.mp4,.webm,.mkv"/>
|
||||
<InputFile id="@fileInputId" OnChange="(e) => UploadMedia(e, row)" hidden accept=".jpg,.jpeg,.png,.gif,.webp,.pdf,.ico,.mp4,.webm,.mkv"/>
|
||||
<label class="ant-btn ant-btn-text ant-btn-icon-only" for="@fileInputId">
|
||||
<Icon Type="@IconType.Outline.Upload"/>
|
||||
</label>
|
||||
|
|
@ -120,6 +120,7 @@
|
|||
MediaTypeNames.Image.Png,
|
||||
MediaTypeNames.Image.Jpeg,
|
||||
MediaTypeNames.Image.Gif,
|
||||
MediaTypeNames.Image.Webp,
|
||||
MediaTypeNames.Application.Pdf,
|
||||
MediaTypeNames.Image.Icon,
|
||||
"video/mp4",
|
||||
|
|
|
|||
|
|
@ -24,12 +24,18 @@
|
|||
<FormItem Label="Recompress existing JPEGs (lossy)">
|
||||
<Switch @bind-Value="@Options.RecompressJpeg" />
|
||||
</FormItem>
|
||||
<FormItem Label="Recompress existing WebP (lossy)">
|
||||
<Switch @bind-Value="@Options.RecompressWebp" />
|
||||
</FormItem>
|
||||
<FormItem Label="Strip metadata (EXIF/ICC/XMP)">
|
||||
<Switch @bind-Value="@Options.StripMetadata" />
|
||||
</FormItem>
|
||||
<FormItem Label="JPEG quality">
|
||||
<AntDesign.InputNumber @bind-Value="@Options.JpegQuality" Min="1" Max="100" />
|
||||
</FormItem>
|
||||
<FormItem Label="WebP quality">
|
||||
<AntDesign.InputNumber @bind-Value="@Options.WebpQuality" Min="1" Max="100" />
|
||||
</FormItem>
|
||||
<FormItem Label="Max long edge (px)">
|
||||
<AntDesign.InputNumber @bind-Value="@Options.MaxLongEdge" Min="256" />
|
||||
</FormItem>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ public class SteamClient
|
|||
var webAssetUri = GetWebAssetUri(appId, webAssetType);
|
||||
var response = await HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, webAssetUri));
|
||||
|
||||
var exists = response.Content.Headers.ContentType.MediaType == MediaTypeNames.Image.Jpeg || response.Content.Headers.ContentType.MediaType == "image/png";
|
||||
var exists = response.Content.Headers.ContentType.MediaType == MediaTypeNames.Image.Jpeg
|
||||
|| response.Content.Headers.ContentType.MediaType == "image/png"
|
||||
|| response.Content.Headers.ContentType.MediaType == MediaTypeNames.Image.Webp;
|
||||
|
||||
return (exists, response.Content.Headers.ContentType.MediaType);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue