Я разработал решение в .NET Core, которое я не собираюсь принимать (все еще жду лучшего ответа).
Проблема с этим решением состоит в том, что обрезка не без потерь (JPEG повторно сжат), и ImageSharp каким-то образом повреждает метаданные изображения - время создания даты отображается как 00:00 в XNView - мне пришлось исправить это с помощью ExifTool копирование метаданных из камеры в формате JPEG.
В противном случае он делает то, что мне нужно.
Изображения размещаются в подпапках пути:
/ S - камера JPEG с уменьшенным разрешением
/ L - переработанные JPEG из RAW с полным разрешением
/ T - целевая папка для обрезанных изображений в полном разрешении
using System;
using System.IO;
using System.Linq;
using ImageSharp;
using SixLabors.Primitives;
namespace fix
{
class Program
{
static void Main(string[] args)
{
var smalls = Directory.GetFiles("path/S").OrderBy(p => p);
var tPath = "path/T/";
foreach (var path in smalls)
{
using (FileStream sStream = File.OpenRead(path))
// change path to full resolution JPEGs from RAWs
using (FileStream lStream = File.OpenRead(path.Replace("/S/", "/L/")))
{
var small = Image.Load(sStream);
var large = Image.Load(lStream);
Rectangle rect = new Rectangle();
// image height of the reduced resolution image with in-camera cropping
// it's always height, the portrait (2:3) mode is only in EXIF
if (small.Height == 1360)
{
// crop rectangle on the full resolution image (see above)
rect = new Rectangle(0, 168, 4000, 2664);
}
// this file has been cropped
if (rect.Width != 0)
{
using (FileStream tStream = File.OpenWrite(string.Format("{0}{1}", tPath, Path.GetFileName(path))))
{
var encoder = new ImageSharp.Formats.JpegEncoder();
encoder.Quality = 98; // as desired
large.Crop(rect).Save(tStream, encoder);
}
}
}
}
}
}
}