#229 Resize cover Images if requested

This commit is contained in:
Glax 2024-08-26 19:34:29 +02:00
parent 3c3f7bb95a
commit e95eb0497c
4 changed files with 54 additions and 34 deletions

View File

@ -200,14 +200,26 @@ public partial class Server : GlobalBase, IDisposable
response.AddHeader("Access-Control-Max-Age", "1728000"); response.AddHeader("Access-Control-Max-Age", "1728000");
response.AppendHeader("Access-Control-Allow-Origin", "*"); response.AppendHeader("Access-Control-Allow-Origin", "*");
if (content is not Stream)
{
response.ContentType = "application/json";
try try
{ {
if (content is Stream stream)
{
response.ContentType = "image/jpeg";
response.AddHeader("Cache-Control", "max-age=600");
stream.CopyTo(response.OutputStream);
response.OutputStream.Close();
stream.Close();
}
else
{
response.ContentType = "application/json";
response.AddHeader("Cache-Control", "no-store");
response.OutputStream.Write(content is not null response.OutputStream.Write(content is not null
? Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(content)) ? Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(content))
: Array.Empty<byte>()); : Array.Empty<byte>());
}
response.OutputStream.Close(); response.OutputStream.Close();
} }
catch (HttpListenerException e) catch (HttpListenerException e)
@ -215,30 +227,6 @@ public partial class Server : GlobalBase, IDisposable
Log(e.ToString()); Log(e.ToString());
} }
} }
else if(content is FileStream stream)
{
string contentType = stream.Name.Split('.')[^1];
switch (contentType.ToLower())
{
case "gif":
response.ContentType = "image/gif";
break;
case "png":
response.ContentType = "image/png";
break;
case "jpg":
case "jpeg":
response.ContentType = "image/jpeg";
break;
default:
response.ContentType = "text/plain";
break;
}
stream.CopyTo(response.OutputStream);
response.OutputStream.Close();
stream.Close();
}
}
public void Dispose() public void Dispose()

View File

@ -1,4 +1,6 @@
using System.Net; using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Tranga.Jobs; using Tranga.Jobs;
using Tranga.MangaConnectors; using Tranga.MangaConnectors;
@ -77,12 +79,37 @@ public partial class Server
manga is null) manga is null)
return new ValueTuple<HttpStatusCode, object?>(HttpStatusCode.NotFound, $"Manga with ID '{groups[1].Value} could not be found.'"); return new ValueTuple<HttpStatusCode, object?>(HttpStatusCode.NotFound, $"Manga with ID '{groups[1].Value} could not be found.'");
string filePath = manga.Value.coverFileNameInCache!; string filePath = manga.Value.coverFileNameInCache!;
if (File.Exists(filePath)) if(!File.Exists(filePath))
return new ValueTuple<HttpStatusCode, object?>(HttpStatusCode.NotFound, "Cover-File not found.");
Bitmap bitmap;
if (requestParameters.TryGetValue("dimensions", out string? dimensionsStr))
{
Regex dimensionsRex = new(@"([0-9]+)x([0-9]+)");
if(!dimensionsRex.IsMatch(dimensionsStr))
return new ValueTuple<HttpStatusCode, object?>(HttpStatusCode.BadRequest, "Requested dimensions not in required format.");
Match m = dimensionsRex.Match(dimensionsStr);
int width = int.Parse(m.Groups[1].Value);
int height = int.Parse(m.Groups[2].Value);
double aspectRequested = (double)width / (double)height;
using Image coverImage = Image.FromFile(filePath);
double aspectCover = (double)coverImage.Width / (double)coverImage.Height;
Size newSize = aspectRequested > aspectCover
? new Size(width, (width / coverImage.Width) * coverImage.Height)
: new Size((height / coverImage.Height) * coverImage.Width, height);
bitmap = new(coverImage, newSize);
}
else
{ {
FileStream coverStream = new(filePath, FileMode.Open); FileStream coverStream = new(filePath, FileMode.Open);
return new ValueTuple<HttpStatusCode, object?>(HttpStatusCode.OK, coverStream); bitmap = new(coverStream);
} }
return new ValueTuple<HttpStatusCode, object?>(HttpStatusCode.NotFound, "Cover-File not found."); using MemoryStream ret = new();
bitmap.Save(ret, ImageFormat.Jpeg);
return new ValueTuple<HttpStatusCode, object?>(HttpStatusCode.OK, ret);
} }
private ValueTuple<HttpStatusCode, object?> GetV2MangaInternalIdChapters(GroupCollection groups, Dictionary<string, string> requestParameters) private ValueTuple<HttpStatusCode, object?> GetV2MangaInternalIdChapters(GroupCollection groups, Dictionary<string, string> requestParameters)

View File

@ -13,6 +13,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PuppeteerSharp" Version="10.0.0" /> <PackageReference Include="PuppeteerSharp" Version="10.0.0" />
<PackageReference Include="Soenneker.Utils.String.NeedlemanWunsch" Version="2.1.301" /> <PackageReference Include="Soenneker.Utils.String.NeedlemanWunsch" Version="2.1.301" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0-preview.7.24405.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -186,12 +186,16 @@ Returns the URL for the Cover of the specified Manga.
* [GET /v2/Manga](#-v2manga) * [GET /v2/Manga](#-v2manga)
* [GET /v2/Connector/*ConnectorName*/GetManga](#-v2connectorconnectornamegetmanga) * [GET /v2/Connector/*ConnectorName*/GetManga](#-v2connectorconnectornamegetmanga)
* [GET /v2/Job/*jobId*](#-v2jobjobid) * [GET /v2/Job/*jobId*](#-v2jobjobid)
Optional: `dimensions=<width>x<height>` replace width and height with requested dimensions in pixels.
Fitting will cover requested area.
</details> </details>
<details> <details>
<summary>Returns</summary> <summary>Returns</summary>
String with the url. String with the url.
If `dimensions=x` was not requested, returns full sized image.
| StatusCode | Meaning | | StatusCode | Meaning |
|------------|--------------------------------------------| |------------|--------------------------------------------|