Image Cropper
TsgcHTMLComponent_ImageCropper:在浏览器中运行的图像裁剪器,适用于头像照片和扫描文档。用户可以裁剪、缩放、旋转和翻转照片,或标出页面的 4 个角以得到一张端正的矩形图像,服务器会在您的代码或磁盘看到结果之前先检查它。适用于 Delphi、C++ Builder 和 .NET。
TsgcHTMLComponent_ImageCropper:在浏览器中运行的图像裁剪器,适用于头像照片和扫描文档。用户可以裁剪、缩放、旋转和翻转照片,或标出页面的 4 个角以得到一张端正的矩形图像,服务器会在您的代码或磁盘看到结果之前先检查它。适用于 Delphi、C++ Builder 和 .NET。
设置结果的形状和大小,然后渲染。用户选择、拖入或粘贴图像,或拍摄照片,并在不向服务器发出请求的情况下编辑。“保存”根据原始像素渲染结果,在浏览器中编码为 JPEG、PNG 或 WebP,并提交给 OnCrop,UploadFolder 则以唯一名称保存文件。
TsgcHTMLComponent_ImageCropper,有照片模式和文档模式
工具栏、编辑器和实时预览,由内嵌在组件中的脚本和 CSS 提供,没有外部库,也不需要 CDN
Delphi, C++ Builder, .NET
一个圆形裁剪器,结果为 512 x 512 的 JPEG。服务器检查图像,以唯一名称把它写入一个文件夹,保存后 TargetSelector 会在页面中显示新头像。
uses
sgcHTML_Component_ImageCropper;
oCropper := TsgcHTMLComponent_ImageCropper.Create(Self);
oCropper.Name := 'AvatarCropper';
oCropper.HTMXEngine := sgcHTMXEngine1;
oCropper.CropperID := 'avatarCropper';
oCropper.CropShape := icsCircle;
oCropper.OutputWidth := 512;
oCropper.OutputHeight := 512;
oCropper.UploadFolder := 'C:\Portal\avatars';
oCropper.UploadURL := '/avatars/'; // 在您的服务器中将其映射到该文件夹
oCropper.TargetSelector := '#avatar';
oCropper.OnCrop := CropperCrop;
oTemplate.BodyContent := '<img id="avatar" src="/avatars/default.jpg" alt="Avatar">' +
oCropper.HTML;
procedure TForm1.CropperCrop(Sender: TObject; const aInfo: TsgcHTMLImageCropInfo;
aStream: TStream; var aAccept: Boolean; var aErrorMessage: string);
begin
// aInfo.URL 是 UploadURL 加上文件获得的唯一名称
StoreAvatarURL(CurrentUserID, aInfo.URL); // 您的数据库
end;
@* Views/Profile/Photo.cshtml *@
@model ProfileModel
<img id="avatar" src="/avatars/current.jpg" alt="Avatar">
<sgc-image-cropper name="avatar" cropper-id="avatarCropper"
crop-shape="circle" output-width="512" output-height="512"
upload-folder="wwwroot/avatars" upload-url="/avatars/"
target-selector="#avatar" aria-label="Change your photo"
on-crop="Model.CheckCrop" />
using esegece.sgcWebSockets;
// Tag Helper 的 OnCrop:图像已由服务器检查
public void CheckCrop(object sender, TsgcHTMLImageCropInfo aInfo, Stream aStream,
ref bool aAccept, ref string aErrorMessage)
{
if (!User.Identity!.IsAuthenticated)
{
aAccept = false;
aErrorMessage = "Sign in to change your photo";
return;
}
Profiles.SetAvatar(User, aInfo.URL);
}
// 在代码中创建的同一裁剪器,用于文档扫描
var cropper = new TsgcHTMLComponent_ImageCropper();
cropper.Name = "ScanCropper";
cropper.HTMXEngine = engine;
cropper.Mode = TsgcHTMLImageCropperMode.icmDocument;
cropper.DocumentFilter = TsgcHTMLImageCropFilter.icflBlackWhite;
cropper.OutputFormat = TsgcHTMLImageCropFormat.icfPNG;
cropper.UploadFolder = @"C:\Portal\scans";
template.BodyContent = cropper.HTML;
一个组件,既是头像和封面的照片编辑器,也是页面和收据的扫描仪。
图像上方有一个带 8 个手柄的矩形:拖动裁剪框可移动它,拖动手柄可调整大小,但绝不会小于源图像的 MinCropSize 像素。AspectRatio 把裁剪框锁定为 16:9 等比例,AspectRatios 列出工具栏的预设,默认是“自由”、1:1、4:3、3:4 和 16:9。
CropShape 的 icsCircle 显示用于头像的圆形遮罩,并把裁剪框锁定为 1:1。PNG 和 WebP 的结果四角透明,JPEG 的结果使用 BackgroundColor。结果的实时缩略图(圆形时为圆的)位于编辑器旁边。
用按钮、鼠标滚轮或双指缩放,范围从 0.5 倍到 16 倍,并在裁剪框之外拖动图像进行平移。向左或向右旋转 90 度,用“拉直”滑块在 -45 度到 45 度之间校正地平线,水平或垂直翻转,“重置”则回到整幅图像。
使用 Mode 的 icmDocument 时,用户把 4 个角拖到页面、收据或白板的四个角上,并有一个 4 倍缩放的放大镜。结果是把四边形映射成端正矩形,并对原始像素进行双线性采样。没有自动边缘检测:角由用户放置。
“原图”、“灰度”、“黑白”、能应对阴影的自适应阈值,以及“增强”(对每个颜色通道做对比度拉伸)。DocumentFilter 设置初始滤镜,用户可在工具栏中更改。
选择文件、拖入、从剪贴板粘贴,或在安全页面上用前置或后置摄像头(FacingMode)拍照。ImageURL 加载初始图像,例如当前头像。照片的 EXIF 方向会被应用,因此用手机拍的竖向照片是正的。
即使是从缩小的副本编辑大图像,结果也始终根据原始像素渲染。OutputFormat 选择 JPEG、PNG 或 WebP,OutputQuality 设置质量,OutputWidth、OutputHeight 和 MaxOutputSize 设置尺寸。浏览器会重新编码结果,因此源文件的 EXIF 和 GPS 数据不会包含在其中。
所有操作都可以用键盘完成:方向键将裁剪框或获得焦点的角移动 1 个像素(按 Shift 为 10 个),Alt+方向键调整裁剪框大小,+ 和 - 缩放,R 旋转。裁剪框和每个角都是带数值文本的滑块,polite 实时区域会播报裁剪尺寸和保存的结果。裁剪器跟随 data-bs-theme="dark" 和减少动态效果的设置。
您最常用到的成员。
服务器绝不信任浏览器。类型必须是 JPEG、PNG 或 WebP 且与 OutputFormat 一致,数据在解码前后都要与 MaxResultSize 对照检查,其魔数字节必须是该类型的,从文件头读出的宽度和高度必须在 MaxOutputSize 范围内与提交的尺寸相等。裁剪数据的每个数字都要检查范围,源文件名会去掉路径部分。
OnCrop(Sender, aInfo, aStream, aAccept, aErrorMessage) 接收已验证的信息和图像字节。请自行保存图像、更改 URL,或把 aAccept 设为 False 并给出您自己的文本。它在请求的线程上触发,sgcHTMLRequestSession 在该线程上提供会话。
使用 UploadFolder 时,服务器会选取由 32 个十六进制字符组成并带有该类型扩展名的唯一名称,绝不使用提交的名称,并且只在图像被接受之后才写入文件。SavedFileName 和 URL(即 UploadURL 加上该名称)会被填充。组件不提供该文件夹:请在您的服务器中把 UploadURL 映射到它。
FieldName 指定一个隐藏的 input,以 data: URL 的形式接收结果,因此外围的表单会连同其他字段一起提交它。TargetSelector 更新每个匹配的 img 元素,DOM 事件 sgc-image-cropped 在每次保存后冒泡,并带有 URL、宽度、高度和类型。没有引擎或 ActionURL 时,“保存”只在浏览器中应用结果。
服务器的文件头读取器是公开的,因此您自己的代码也可以用同样的规则检查图像:sgcHTMLImageInfo(aStream, aType, aWidth, aHeight) 无需解码即可读取 PNG、JPEG 或 WebP 图像的类型和尺寸。在 .NET 中它是 sgcHTMLImageCropperHelpers 的静态方法。
window.sgcImageCropper 提供 scan、instances、get、load、loadFile、setCrop、reset、result 和 save。脚本会初始化页面上的每个裁剪器,包括 htmx 换入之后的,同一页上的多个裁剪器共用它。
在 Razor 视图中,<sgc-image-cropper> Tag Helper 渲染裁剪器,“保存”提交到 UseSgcHtml 的组件事件端点。不在其特性取值列表中的值会在页面渲染时抛出 InvalidOperationException,Kestrel 的 MaxRequestBodySize 仍会限制请求大小。
Demos\60.HTML\01.RunTime\33.ImageCropper 是 sgc Profile Studio,一个在端口 8135 上的服务器,有三个裁剪器:通过 OnCrop 保存的圆形头像、带黑白滤镜并把每次扫描保存在 UploadFolder 中的文档扫描仪,以及通过 FieldName 随表单提交的 16:9 产品封面。设计时、Lazarus 和 .NET 版本与之对应。