Move photo processing code to a general class.

This commit is contained in:
2019-06-01 01:44:03 +01:00
parent a57a8b4b8e
commit c43f88a936
5 changed files with 220 additions and 206 deletions

View File

@@ -1,12 +1,10 @@
using System; using System;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Cicm.Database;
using Cicm.Database.Models; using Cicm.Database.Models;
using cicm_web.Areas.Admin.Models; using cicm_web.Areas.Admin.Models;
using cicm_web.Helpers;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
@@ -15,11 +13,6 @@ using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SkiaSharp;
namespace cicm_web.Areas.Admin.Controllers namespace cicm_web.Areas.Admin.Controllers
{ {
@@ -165,202 +158,8 @@ namespace cicm_web.Areas.Admin.Controllers
return View(machinePhoto); return View(machinePhoto);
} }
Image<Rgba32> image = Image.Load(tmpFile); MachinePhoto photo = Photos.Add(tmpFile, newId, hostingEnvironment.WebRootPath,
hostingEnvironment.ContentRootPath, extension);
MachinePhoto photo = new MachinePhoto();
foreach(ImageProperty prop in image.MetaData.Properties)
switch(prop.Name)
{
case "aux:Lens":
photo.Lens = prop.Value;
break;
}
foreach(ExifValue exif in image.MetaData.ExifProfile.Values.ToList())
switch(exif.Tag)
{
case ExifTag.Artist:
photo.Author = exif.Value as string;
break;
case ExifTag.Make:
photo.CameraManufacturer = exif.Value as string;
break;
case ExifTag.ColorSpace:
photo.ColorSpace = (ColorSpace)exif.Value;
break;
case ExifTag.UserComment:
photo.Comments = Encoding.ASCII.GetString(exif.Value as byte[]);
break;
case ExifTag.Contrast:
photo.Contrast = (Contrast)exif.Value;
break;
case ExifTag.DateTimeDigitized:
photo.CreationDate =
DateTime.ParseExact(exif.Value.ToString(), "yyyy:MM:dd HH:mm:ss",
CultureInfo.InvariantCulture);
break;
case ExifTag.DigitalZoomRatio:
photo.DigitalZoomRatio = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.ExifVersion:
photo.ExifVersion = Encoding.ASCII.GetString(exif.Value as byte[]);
break;
case ExifTag.ExposureTime:
{
Rational rat = (Rational)exif.Value;
photo.Exposure = rat.Denominator == 1 ? rat.Numerator.ToString() : rat.ToString();
break;
}
case ExifTag.ExposureMode:
photo.ExposureMethod = (ExposureMode)exif.Value;
break;
case ExifTag.ExposureProgram:
photo.ExposureProgram = (ExposureProgram)exif.Value;
break;
case ExifTag.Flash:
photo.Flash = (Flash)exif.Value;
break;
case ExifTag.FNumber:
photo.Focal = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.FocalLength:
photo.FocalLength = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.FocalLengthIn35mmFilm:
photo.FocalLengthEquivalent = exif.Value as ushort?;
break;
case ExifTag.XResolution:
photo.HorizontalResolution = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.ISOSpeedRatings:
photo.IsoRating = (ushort)exif.Value;
break;
case ExifTag.LensModel:
photo.Lens = exif.Value as string;
break;
case ExifTag.LightSource:
photo.LightSource = (LightSource)exif.Value;
break;
case ExifTag.MeteringMode:
photo.MeteringMode = (MeteringMode)exif.Value;
break;
case ExifTag.ResolutionUnit:
photo.ResolutionUnit = (ResolutionUnit)exif.Value;
break;
case ExifTag.Orientation:
photo.Orientation = (Orientation)exif.Value;
break;
case ExifTag.Saturation:
photo.Saturation = (Saturation)exif.Value;
break;
case ExifTag.SceneCaptureType:
photo.SceneCaptureType = (SceneCaptureType)exif.Value;
break;
case ExifTag.SensingMethod:
photo.SensingMethod = (SensingMethod)exif.Value;
break;
case ExifTag.Software:
photo.SoftwareUsed = exif.Value as string;
break;
case ExifTag.SubjectDistanceRange:
photo.SubjectDistanceRange = (SubjectDistanceRange)exif.Value;
break;
case ExifTag.YResolution:
photo.VerticalResolution = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.WhiteBalance:
photo.WhiteBalance = (WhiteBalance)exif.Value;
break;
default:
image.MetaData.ExifProfile.RemoveValue(exif.Tag);
break;
}
if(!Directory.Exists(Path.Combine(hostingEnvironment.WebRootPath, "assets", "photos")))
Directory.CreateDirectory(Path.Combine(hostingEnvironment.WebRootPath, "assets", "photos"));
if(!Directory.Exists(Path.Combine(hostingEnvironment.WebRootPath, "assets", "photos", "machines")))
Directory.CreateDirectory(Path.Combine(hostingEnvironment.WebRootPath, "assets", "photos", "machines"));
if(!Directory.Exists(Path.Combine(hostingEnvironment.WebRootPath, "assets", "photos", "machines", "thumbs"))
)
Directory.CreateDirectory(Path.Combine(hostingEnvironment.WebRootPath, "assets", "photos", "machines",
"thumbs"));
string outJpeg = Path.Combine(hostingEnvironment.WebRootPath, "assets", "photos", "machines",
newId + ".jpg");
using(FileStream jpegStream =
new FileStream(outJpeg, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
image.SaveAsJpeg(jpegStream);
int imgMax = Math.Max(image.Width, image.Height);
int width = image.Width;
int height = image.Height;
image.Dispose();
SKBitmap skBitmap = SKBitmap.Decode(outJpeg);
foreach(string format in new[] {"jpg", "webp"})
{
if(!Directory.Exists(Path.Combine(hostingEnvironment.WebRootPath, "assets/photos/machines/thumbs",
format))) ;
Directory.CreateDirectory(Path.Combine(hostingEnvironment.WebRootPath, "assets/photos/machines/thumbs",
format));
SKEncodedImageFormat skFormat;
switch(format)
{
case "webp":
skFormat = SKEncodedImageFormat.Webp;
break;
default:
skFormat = SKEncodedImageFormat.Jpeg;
break;
}
foreach(int multiplier in new[] {1, 2, 3})
{
if(!Directory.Exists(Path.Combine(hostingEnvironment.WebRootPath, "assets/photos/machines/thumbs",
format, $"{multiplier}x"))) ;
Directory.CreateDirectory(Path.Combine(hostingEnvironment.WebRootPath,
"assets/photos/machines/thumbs", format, $"{multiplier}x"));
string resized = Path.Combine(hostingEnvironment.WebRootPath, "assets/photos/machines/thumbs",
format, $"{multiplier}x", newId + $".{format}");
if(System.IO.File.Exists(resized)) continue;
float canvasMin = 256 * multiplier;
float scale = canvasMin / imgMax;
// Do not enlarge images
if(scale > 1) scale = 1;
SKBitmap skResized = skBitmap.Resize(new SKImageInfo((int)(width * scale), (int)(height * scale)),
SKFilterQuality.High);
SKImage skImage = SKImage.FromBitmap(skResized);
SKData data = skImage.Encode(skFormat, 100);
FileStream outfs = new FileStream(resized, FileMode.CreateNew);
data.SaveTo(outfs);
outfs.Close();
}
}
if(!Directory.Exists(Path.Combine(hostingEnvironment.ContentRootPath, "originals", "photos")))
Directory.CreateDirectory(Path.Combine(hostingEnvironment.ContentRootPath, "originals", "photos"));
if(!Directory.Exists(Path.Combine(hostingEnvironment.ContentRootPath, "originals", "photos")))
Directory.CreateDirectory(Path.Combine(hostingEnvironment.ContentRootPath, "originals", "photos"));
if(!Directory.Exists(Path.Combine(hostingEnvironment.ContentRootPath, "originals", "photos", "machines")))
Directory.CreateDirectory(Path.Combine(hostingEnvironment.ContentRootPath, "originals", "photos",
"machines"));
System.IO.File.Move(tmpFile,
Path.Combine(hostingEnvironment.ContentRootPath, "originals", "photos", "machines",
newId + extension));
photo.Id = newId; photo.Id = newId;
photo.User = await userManager.GetUserAsync(HttpContext.User); photo.User = await userManager.GetUserAsync(HttpContext.User);

View File

@@ -0,0 +1,214 @@
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Cicm.Database;
using Cicm.Database.Models;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SkiaSharp;
namespace cicm_web.Helpers
{
public class Photos
{
public static MachinePhoto Add(string tmpFile, Guid newId, string webRootPath, string contentRootPath,
string extension)
{
Image<Rgba32> image = Image.Load(tmpFile);
MachinePhoto photo = new MachinePhoto();
foreach(ImageProperty prop in image.MetaData.Properties)
switch(prop.Name)
{
case "aux:Lens":
photo.Lens = prop.Value;
break;
}
foreach(ExifValue exif in image.MetaData.ExifProfile.Values.ToList())
switch(exif.Tag)
{
case ExifTag.Artist:
photo.Author = exif.Value as string;
break;
case ExifTag.Make:
photo.CameraManufacturer = exif.Value as string;
break;
case ExifTag.ColorSpace:
photo.ColorSpace = (ColorSpace)exif.Value;
break;
case ExifTag.UserComment:
photo.Comments = Encoding.ASCII.GetString(exif.Value as byte[]);
break;
case ExifTag.Contrast:
photo.Contrast = (Contrast)exif.Value;
break;
case ExifTag.DateTimeDigitized:
photo.CreationDate =
DateTime.ParseExact(exif.Value.ToString(), "yyyy:MM:dd HH:mm:ss",
CultureInfo.InvariantCulture);
break;
case ExifTag.DigitalZoomRatio:
photo.DigitalZoomRatio = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.ExifVersion:
photo.ExifVersion = Encoding.ASCII.GetString(exif.Value as byte[]);
break;
case ExifTag.ExposureTime:
{
Rational rat = (Rational)exif.Value;
photo.Exposure = rat.Denominator == 1 ? rat.Numerator.ToString() : rat.ToString();
break;
}
case ExifTag.ExposureMode:
photo.ExposureMethod = (ExposureMode)exif.Value;
break;
case ExifTag.ExposureProgram:
photo.ExposureProgram = (ExposureProgram)exif.Value;
break;
case ExifTag.Flash:
photo.Flash = (Flash)exif.Value;
break;
case ExifTag.FNumber:
photo.Focal = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.FocalLength:
photo.FocalLength = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.FocalLengthIn35mmFilm:
photo.FocalLengthEquivalent = exif.Value as ushort?;
break;
case ExifTag.XResolution:
photo.HorizontalResolution = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.ISOSpeedRatings:
photo.IsoRating = (ushort)exif.Value;
break;
case ExifTag.LensModel:
photo.Lens = exif.Value as string;
break;
case ExifTag.LightSource:
photo.LightSource = (LightSource)exif.Value;
break;
case ExifTag.MeteringMode:
photo.MeteringMode = (MeteringMode)exif.Value;
break;
case ExifTag.ResolutionUnit:
photo.ResolutionUnit = (ResolutionUnit)exif.Value;
break;
case ExifTag.Orientation:
photo.Orientation = (Orientation)exif.Value;
break;
case ExifTag.Saturation:
photo.Saturation = (Saturation)exif.Value;
break;
case ExifTag.SceneCaptureType:
photo.SceneCaptureType = (SceneCaptureType)exif.Value;
break;
case ExifTag.SensingMethod:
photo.SensingMethod = (SensingMethod)exif.Value;
break;
case ExifTag.Software:
photo.SoftwareUsed = exif.Value as string;
break;
case ExifTag.SubjectDistanceRange:
photo.SubjectDistanceRange = (SubjectDistanceRange)exif.Value;
break;
case ExifTag.YResolution:
photo.VerticalResolution = ((Rational)exif.Value).ToDouble();
break;
case ExifTag.WhiteBalance:
photo.WhiteBalance = (WhiteBalance)exif.Value;
break;
default:
image.MetaData.ExifProfile.RemoveValue(exif.Tag);
break;
}
if(!Directory.Exists(Path.Combine(webRootPath, "assets", "photos")))
Directory.CreateDirectory(Path.Combine(webRootPath, "assets", "photos"));
if(!Directory.Exists(Path.Combine(webRootPath, "assets", "photos", "machines")))
Directory.CreateDirectory(Path.Combine(webRootPath, "assets", "photos", "machines"));
if(!Directory.Exists(Path.Combine(webRootPath, "assets", "photos", "machines", "thumbs")))
Directory.CreateDirectory(Path.Combine(webRootPath, "assets", "photos", "machines", "thumbs"));
string outJpeg = Path.Combine(webRootPath, "assets", "photos", "machines", newId + ".jpg");
using(FileStream jpegStream =
new FileStream(outJpeg, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
image.SaveAsJpeg(jpegStream);
int imgMax = Math.Max(image.Width, image.Height);
int width = image.Width;
int height = image.Height;
image.Dispose();
SKBitmap skBitmap = SKBitmap.Decode(outJpeg);
foreach(string format in new[] {"jpg", "webp"})
{
if(!Directory.Exists(Path.Combine(webRootPath, "assets/photos/machines/thumbs", format))) ;
Directory.CreateDirectory(Path.Combine(webRootPath, "assets/photos/machines/thumbs", format));
SKEncodedImageFormat skFormat;
switch(format)
{
case "webp":
skFormat = SKEncodedImageFormat.Webp;
break;
default:
skFormat = SKEncodedImageFormat.Jpeg;
break;
}
foreach(int multiplier in new[] {1, 2, 3})
{
if(!Directory.Exists(Path.Combine(webRootPath, "assets/photos/machines/thumbs", format,
$"{multiplier}x"))) ;
Directory.CreateDirectory(Path.Combine(webRootPath, "assets/photos/machines/thumbs", format,
$"{multiplier}x"));
string resized = Path.Combine(webRootPath, "assets/photos/machines/thumbs", format,
$"{multiplier}x", newId + $".{format}");
if(File.Exists(resized)) continue;
float canvasMin = 256 * multiplier;
float scale = canvasMin / imgMax;
// Do not enlarge images
if(scale > 1) scale = 1;
SKBitmap skResized = skBitmap.Resize(new SKImageInfo((int)(width * scale), (int)(height * scale)),
SKFilterQuality.High);
SKImage skImage = SKImage.FromBitmap(skResized);
SKData data = skImage.Encode(skFormat, 100);
FileStream outfs = new FileStream(resized, FileMode.CreateNew);
data.SaveTo(outfs);
outfs.Close();
}
}
if(!Directory.Exists(Path.Combine(contentRootPath, "originals", "photos")))
Directory.CreateDirectory(Path.Combine(contentRootPath, "originals", "photos"));
if(!Directory.Exists(Path.Combine(contentRootPath, "originals", "photos")))
Directory.CreateDirectory(Path.Combine(contentRootPath, "originals", "photos"));
if(!Directory.Exists(Path.Combine(contentRootPath, "originals", "photos", "machines")))
Directory.CreateDirectory(Path.Combine(contentRootPath, "originals", "photos", "machines"));
File.Move(tmpFile, Path.Combine(contentRootPath, "originals", "photos", "machines", newId + extension));
return photo;
}
}
}

View File

@@ -34,7 +34,7 @@ using Cicm.Database.Models;
using SkiaSharp; using SkiaSharp;
using SKSvg = SkiaSharp.Extended.Svg.SKSvg; using SKSvg = SkiaSharp.Extended.Svg.SKSvg;
namespace cicm_web namespace cicm_web.Helpers
{ {
public static class SvgRender public static class SvgRender
{ {

View File

@@ -32,6 +32,7 @@ using System;
using System.Linq; using System.Linq;
using Cicm.Database; using Cicm.Database;
using Cicm.Database.Models; using Cicm.Database.Models;
using cicm_web.Helpers;
using DiscImageChef.Interop; using DiscImageChef.Interop;
using Markdig; using Markdig;
using Microsoft.AspNetCore; using Microsoft.AspNetCore;

View File

@@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp2.2</TargetFramework>
<Version>3.0.99.688</Version> <Version>3.0.99.695</Version>
<Company>Canary Islands Computer Museum</Company> <Company>Canary Islands Computer Museum</Company>
<Copyright>Copyright © 2003-2018 Natalia Portillo</Copyright> <Copyright>Copyright © 2003-2018 Natalia Portillo</Copyright>
<Product>Canary Islands Computer Museum Website</Product> <Product>Canary Islands Computer Museum Website</Product>