Вы можете попробовать net-vips , привязку C # для libvips . Это ленивая, потоковая, управляемая по требованию библиотека обработки изображений, поэтому она может выполнять такие операции без необходимости загружать все изображение.
Нет операции, которая могла бы напрямую выполнить наклонную обрезку, но ее легко сделать самостоятельно с помощью небольшого триггера.
Например, используя привязку libvips для Python (извините, у меня здесь не установлен C #, но API тот же):
#!/usr/bin/python3
import sys
import math
import pyvips
image = pyvips.Image.new_from_file(sys.argv[1])
out_filename = sys.argv[2]
top_left_x = int(sys.argv[3])
top_left_y = int(sys.argv[4])
top_right_x = int(sys.argv[5])
top_right_y = int(sys.argv[6])
bottom_right_x = int(sys.argv[7])
bottom_right_y = int(sys.argv[8])
# the angle the top edge is rotated by
dx = top_right_x - top_left_x
dy = top_right_y - top_left_y
angle = math.degrees(math.atan2(dx, dy))
if angle < -45 or angle >= 45:
angle = 90 - angle
# therefore the angle to rotate by to get it straight
angle = -angle
image = image.rotate(angle)
# the new position of the rectangle in the rotated image
c = math.cos(math.radians(angle))
s = math.sin(math.radians(angle))
left = top_left_x * c - top_left_y * s
top = top_left_x * s + top_left_y * c
width = math.hypot(top_right_x - top_left_x, top_right_y - top_left_y)
height = math.hypot(top_right_x - bottom_right_x, top_right_y - bottom_right_y)
# after a rotate, the new position of the origin is given by .xoffset, .yoffset
tile = image.crop(left + image.xoffset, top + image.yoffset, width, height)
tile.write_to_file(out_filename)
Я могу запустить его на большом изображении:
$ vipsheader ~/pics/openslide/bild.ndpi
/home/john/pics/openslide/bild.ndpi: 126976x98304 uchar, 4 bands, rgb, openslideload
$ time ./angled_crop.py ~/pics/openslide/bild.ndpi x.jpg 680 760 936 836 484 1552
real 0m0.304s
user 0m0.388s
sys 0m0.040s
Таким образом, требуется 0,3 с, чтобы обрезать небольшую угловую область из изображения с разрешением 127000 x 98000 пикселей.
Изображения Openslide представляют собой (приблизительно) мозаичный рисунок, поэтому для декодирования необходимо только декодировать части входного изображения.
Это будет работать и на несвязанных изображениях, хотя сначала нужно будет декодировать все изображение целиком. Он будет декодироваться в память для изображений размером менее 100 МБ, а во временный файл в противном случае.