-
Notifications
You must be signed in to change notification settings - Fork 0
/
ImageProcessor.cs
145 lines (105 loc) · 4.32 KB
/
ImageProcessor.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
145
using ImageMagick;
using System.IO.Compression;
using System.Text.Json;
namespace covergen;
internal class ImageProcessor
{
private MagickGeometry SquareMagickGeometry { get; } = new("1:1");
private MagickGeometry ResizeMagickGeometry { get; }
private readonly int _coverWidth;
internal ImageProcessor(int coverWidth)
{
_coverWidth = coverWidth;
ResizeMagickGeometry = new MagickGeometry(coverWidth);
}
private bool Process(DirectoryInfo di)
{
#region Local Method
string GetOutputCoverPath() => Path.Combine(di.
FullName, "cover.webp");
FileInfo GetImageSourceZipFileInfo()
{
var zipFileInfosInWvDir = di.GetFiles("*.zip");
FileInfo? fileInfo = zipFileInfosInWvDir.FirstOrDefault(zfi => zfi.Name == "base.zip") ??
zipFileInfosInWvDir.FirstOrDefault(zfi => zfi.Name == "orig.zip");
if (fileInfo == null) throw new FileNotFoundException($"Could not be found base.zip or orig.zip in {di.FullName}");
return fileInfo;
}
ZipArchiveEntry GetImageEntry(ZipArchive archive)
{
ZipArchiveEntry? imageEntry = archive.Entries.FirstOrDefault(entry => entry.FullName.EndsWith(".webp") || entry.FullName.EndsWith(".jpg"));
if (imageEntry == null) throw new FileNotFoundException($"Could not be found Image file in imageSourceZip");
return imageEntry;
}
Config? GetConfig(ZipArchive archive)
{
ZipArchiveEntry? configEntry = archive.GetEntry("config.json");
if (configEntry == null) return null;
using Stream configStream = configEntry.Open();
using StreamReader streamReader = new(configStream);
string jsonString = streamReader.ReadToEnd();
return JsonSerializer.Deserialize<Config>(jsonString);
}
void Crop(MagickImage image, Crop cropSetting)
{
MagickGeometry cropMagickGeometry = cropSetting.GetMagickGeometry(image.Width, image.Height);
image.Crop(cropMagickGeometry);
image.RePage();
Console.WriteLine($"cropped: {image.Width}x{image.Height}");
}
void CenterSquareCropAndSaveToFile(MagickImage image)
{
image.Crop(SquareMagickGeometry, Gravity.Center);
image.RePage();
// Save Image.bmp to Tmp Dir
image.Write(@"tmp\cover.png");
Console.WriteLine($"center cropped: {image.Width}x{image.Height}");
}
void UpScale(int ratio, int noiseLevel)
{
Waifu2xUpScaler.UpscaleAndDenoise( noiseLevel, ratio);
}
void DownScaleAndSaveToFile()
{
using MagickImage image_cover = new(@"tmp\cover_upscaled.png");
image_cover.Resize(ResizeMagickGeometry);
//convert to webp and write to File
image_cover.Write(GetOutputCoverPath());
}
#endregion
// Get ImageSource zip file
FileInfo imageSourceZipFileInfo = GetImageSourceZipFileInfo();
// OpenRead Zip Archive
using ZipArchive archive = ZipFile.OpenRead(imageSourceZipFileInfo.FullName);
// Get ImageEntry
ZipArchiveEntry imageEntry = GetImageEntry(archive);
// Open Image Stream
using Stream imageStream = imageEntry.Open();
using MagickImage image = new(imageStream);
Config? config = GetConfig(archive);
Crop? cropSetting = config?.Crop;
// Apply crop setting in config file
if (cropSetting != null) Crop(image, cropSetting);
// Center Crop into AspectRatio 1:1
CenterSquareCropAndSaveToFile(image);
// Caculate UpScale ratio
int ratio = ScaleRatioCaculator.CalculateRatio(image.Width, _coverWidth);
int noiseLevel = config?.Noise ?? 0;
UpScale(ratio, noiseLevel);
DownScaleAndSaveToFile();
return true;
}
internal void ProcessAll(DirectoryInfo[] dis)
{
static void ShowProgress(ref int counter)
{
Console.WriteLine($"{++counter} covers generate");
}
int counter = 0;
Directory.CreateDirectory("tmp");
foreach (var di in dis)
{
if (Process(di)) ShowProgress(ref counter);
}
}
}