我不建议将所有内容组合成一个图像,因为您将延迟任何图像的“初始外观”,直到整个文件下载。最好让可见的东西尽快加载并优化其余部分以提高整体吞吐量。
例如,如果图像每个小于 50KB,将它们组合为精灵图像可能是有意义的,但我建议一次组合 10 个。如果图像很小,比如每个 5KB,一次 30 个是合理的。
您需要担心一系列瓶颈
- HTTP 开销和并发连接限制(精灵图像对此有帮助)
- 服务器吞吐量开销(可通过正确的磁盘缓存和边缘缓存解决)
- 浏览器渲染开销(精灵最适合图标和小缩略图;它们不应该很大,尽量保持在 1 兆像素以下)。
将现有图像连接在一起并以 jpeg 形式重新压缩有时可以提高压缩率,有时会引入伪影。例如,混合线条艺术和照片是一个坏主意。Jpeg不擅长线条艺术。如果需要,可以使用 PNG,甚至是 PNG-8。有时您会发现 100% 质量的 JPEG 最终小于 GIF 或 PNG 版本,但大多数时候,线条艺术最好以 PNG 格式存储。
如果您有这些照片的 ID,并计划使用磁盘缓存进行动态路由,它确实可以显着简化您的任务。
ImageResizer库可让您轻松“插入”其动态管道和磁盘缓存系统。
在这种情况下,您将实现IVirtualImageProvider
and IVirtualBitmapFile
。有关生成位图并让管道处理其余部分的简单示例,请参阅渐变插件。
您必须定义您的 url 语法并在 FileExists 和 GetFile 方法中查找它。/combine-images.ashx?idlist=34,56,79,23&dir=horizontal&width=50&height=50 之类的东西。
然后,您必须加载每个图像,使用托管 API将其大小调整为位图实例,然后将其绘制在您分配的画布上。
您的大部分瓶颈可能在于从 SQL 中提取图像。如果服务器上的 RAM 有限,串行方法可能比并行方法更安全(即,一次从 SQL 获取一个图像,调整大小并绘制它,处理数据,然后继续)。如果您的源图像开始时很小,则多线程方法可能没问题。请记住,即使它被磁盘缓存,您也需要使其快速,因为请求默认在 30 秒后超时。正确完成后,您应该能够在 2 秒内使用空磁盘缓存提供 10 个图像精灵,缓存后为 20 毫秒。
如果这看起来有点压倒性,我确实提供自定义插件开发,但有一个队列。
每个请求 1 个文件的方法有很多优点,在加入 Sprite 潮流之前,可能值得尝试 ImageResizer 的磁盘缓存和 SqlReader 插件。并不是说这是错误的方法,但未缓存的 MVC+SQL 可能会增加很多开销。