使用裁剪器以缩小的尺寸缩放和移动图形 - 我的方法合理吗?

Zooming and moving a graphic at a reduced size using a cropper - is my method sound?

我希望这个问题在堆栈溢出中没问题。

我正在编写一些代码,但在这个阶段只完成了算法,想知道我是否正在以最好的方式解决这个问题?

这是我需要做的:

拍摄一张 2000x2000 像素的图像并使用现有的 JS/Jquery crop/scale 库(尚未确定任何特定的库 - 欢迎提出建议)并允许用户四处移动此图像并放大和出来,所以它适合 1000x1000 的区域。此 "cropped/zoomed" 1000x1000 区域将成为用户的最终输出图像。

然而,在实际 UI 中,出于将其安装在特定 space 中的原因,我需要用户以一半的尺寸工作。因此,他们的 1000x1000 "final image" 区域由 500x500px 区域表示。希望这是有道理的。

这是我提出的算法:

原始 2000px x 2000px 图像是 source.png

  1. 使用 source.png 并使用 ImageMagick 或类似工具在 PHP 中将其大小调整 50%,然后通过 Ajax 将这张新的 "temporary" 1000x1000 图像反馈给我的代码。
  2. 使用 cropper/scaler 在 500x500 工作区后面显示此临时图像,并允许用户 crop/move。
  3. 当用户完成后,将 crop/zoom 坐标从缩放器代码发送到 PHP 例程,该例程通过 ImageMagick 将原始 source.png 裁剪为新的 1000px x 1000px 图像将 X、Y、H、W 乘以 2,并将缩放(比例)除以 2。

我认为这可行,想知道是否有人认为这是执行此操作的最佳方法,还是我遗漏了一些非常明显的东西。

由于以上含糊不清而编辑:

基本上这就是我正在创建的内容:应用程序输出一个 1000x1000 像素的图像,上面有用户 selected 文本(没有提到,以免过于复杂)。 2000x2000 图片的作用是用户可以 select 多张图片,这将成为文本后面的背景图片。用户可以移动和缩放该背景图像,以便他们想要的位显示为最终 1000x1000 输出中的背景。但是工作区只有500x500.

首先,消除 "application space" 与 "user space" 的歧义。

如您所述,图像(任何给定尺寸)必须适合 1000x1000 的区域。这将是您的应用程序 space,应用程序所关注的 space。

之后,浏览器不加选择地将应用程序 space 的大小调整了 50%...但实际上,这将是在向用户显示之前应用到显示器的最终转换。这是用户关心的'user space'、space

综上所述,您真正需要处理的是确保您的 2000x2000 图像缩小到给定的应用程序 space(1000x1000)。应用所有这些翻译后,然后应用最后的 50% 缩小。

但无论如何,您在这里真正想要的是知道拍摄任何尺寸的图像,并知道将其缩小多少以使其按比例适合 1000x1000 的应用 space,因此您需要一些数学。

我假设此时您将在应用程序中使用 javascript,但它也可以轻松应用于 php。

您需要知道源尺寸 (2000x2000) 和目标尺寸 (1000x1000)。只需要一点数学。我假设这就是您想要的,因为我已经意识到这是一种非常常见的编程模式,用于 'fitting' 一个事物按比例在另一个事物中。我觉得每个程序员最终都会学会这个公式...

var source = {w: 2000, h: 2000};
var dest = {w: 1000, h: 1000};

// here's the magic... how many times each source "fits" in the dest along each dimension
var sourceFits = {
   w: dest.w / source.w
   h: dest.h / source.h
};

// In this case, the source can fit x2 along each of the destination dimensions.
// that means that sourceFits.w = 0.5 and sourceFits.h = 0.5. It's a perfect fit
// for either dimension. It doesn't make for a compelling example, but it will work for
// ANY provided source or dest size. 

// So, now that we know how snugly each of the source dimensions fit in the destination,
// we can choose that as the most appropriate scale... lets pick the smaller of the two.
var smallerFits = sourceFits.w > sourceFits.h ? sourceFits.h : sourceFits.w;

// To make the image 'fit inside' we just scale it down by the smaller dimension...
var newSourceSize = {w: source.w * smallerFits, h: source.h * smallerFits}

您的问题有点含糊,因此很难判断这是否确实是您正在寻找的解决方案。希望它适用于您的情况?

您的方法完全有效。事实上,我会选择你的方法而不是其他方法。我会解释...

基本上,您可以通过两种主要方式来实施您所解释的解决方案。

您提出的方法被认为是 'backend resize' 实现,因为您让 ImageMagick 通过 AJAX(位置图像,比例,等等。只是一些数字。) - 但然后在 'backend'

上执行 resize/storage

你可以做一个 'frontend resize',其中你让 JavaScript 操作获取图像,将其缩小,然后将其重新表示为二进制,然后推送上线。您将需要 resized/cropped 图像的原始二进制文件,因为调整大小的版本实际上并不存在于磁盘上的任何位置(因此您也不能执行典型的 'POST' 操作),除非用户首先保存图片并重新上传(这并不理想)

但我会提倡后端调整大小...为什么?安全性。远不容易被前端注入。恶意用户可以加载 cropping/resize 的图像,然后使用 JS 注入插入他们选择的新图像(出于恶意。想想裸体等),然后 post 将其返回到您的服务器上。或者更糟的是,一个非常聪明的用户可以在您的图像中编码恶意脚本,然后在将其上传到您的服务器后执行它。

另一个考虑因素是一致性;当你让 'central point' 处理调整大小时,你会变得不那么依赖 JS 的行为一致(或者甚至根本不依赖某些浏览器),就像后端实现一样。

通过 AJAX 脚本只接受用户的一些数字(并正确验证数字),恶意用户恶意攻击您网站的范围要小得多。

当然,通过数学计算很烦人,而不是仅仅挖掘完美调整大小的前端内容,但这实际上是必需的。

使用ImageMagick怎么样?当然没有'perfect'工具,要不你就用吧。也就是说,您需要衡量该工具是否最适合您的项目。一些注意事项...

  • 规模:老实说,我们并没有在这里完全使用 ImageMagick。这是一个简单的调整大小操作,所以我们可以使用 'dumber' 库来 处理它。我们现在正在使用一个巨大的二进制库来使用 1% 它的功能,我认为这是对服务器 space 的浪费。
  • 部署:想象一下有一天您发现自己需要迁移 到不同的托管服务提供商。如果该提供商 'does not support' ImageMagick,您会发现自己以一种方式重写代码 将使您的站点继续运行。
  • 可用性:如果您知道 ImageMagick 将在 生产服务器。这是一个很棒的图书馆,而且非常容易使用, 特别是 PHP 实现。 PHP GD 库 更有可能部署在默认 PHP 服务器上,并且所有 要让这些继续下去需要一些基本的数学(参考我之前的 回答,除非你需要一个 PHP 实现)

综上所述,根据您可能的考虑,我会选择仅使用一些简单的 GD PHP 功能(结合 'backend resize' 方法)。

另一种选择是利用代码库,它更侧重于对图像执行灯光更改。我找到的一个优秀的库是 TimThumb。它只是你服务器上的一个隐藏 PHP 文件——你给它一些 GET 参数(源图像 url、目标大小、调整大小模式、一些过滤器、对齐方式......随便你喜欢什么)和加载结果将是请求的图像。它支持缓存请求,因此如果您发现自己经常执行相同的调整大小,它可以轻松地 return 以前调用的转换。

然而,TimThumb appears to lack support for distinctly positioning an image,这又回到了 'not a good solution' 的领域 - 所以坚持使用一些手写的 GD PHP 函数会很好地工作(除了令人沮丧的冗长的编程术语那是 GD 函数名称,wink)

希望对您有所帮助!请参阅我之前的回答以获取有关后端调整大小操作等的帮助