如何使用CFImage调整大小并实际缩小图像文件大小?

3
可能重复:
如果调整大小不会减小文件大小并且图片质量下降,为什么我要在ColdFusion中调整图像大小? 我在这里一定做错了...使用Coldfusion8。
我有一个产品搜索,从外部服务器拉取图像,因此我需要在运行时设置图像。
假设我有一个 500x500 像素、111kb 的 jpg,我从外部服务器抓取它。
现在我正在这样做:
<cfimage name="myImage" source="#bildpfad##bilddateiname#" action="read" />
<cfif IsImage(myImage) is true>
    <cfscript>
    ImageSetAntialiasing(myImage,"on");
    variables.breite = 400;
        ImageScaleToFit(myImage, variables.breite,"", "highestPerformance");
    </cfscript>
<cfxml variable="imageXml">
    <cfimage action="writetobrowser" source="#myImage#" />
</cfxml>
<cfoutput><div class="resultsImgWrap">#imageXml#</div></cfoutput>

这可以正确显示图片,但是当我检查文件大小时,发现

400x400px 111.2kB

如果我使用IrfanView,只是减小文件大小并保存图像,那么文件大小已经达到65kb。

问题: 如果我调整图像大小,如何让CFIMAGE减小文件大小?如果大小保持在111kb,为什么要使用CFIMAGE,而不是简单地将图像作为纯HTML添加。

**编辑:
变量Bildpfad和Bilddateiname将类似于:

bildpfad (path to image):         http://www.some-server.com/images/
bilddateiname (filename):         some_image123.jpg

你的数字是否正确,因为11.2kB < 111kb,所以你得到了你想要的结果。 - nosilleg
我认为任何图像调整大小都不会修改图像本身,只是改变了它的显示方式,因此文件大小始终保持不变。 - Limey
@nosilleg:我希望能够...但它是111.2kb :-( - frequent
@Limey:如果是那样的话,我真的可以跳过所有CFIMAGE处理,不是吗?虽然我认为这不正确。 - frequent
你之前说的是“400x400像素 11.2千字节”,而不是111.2千字节。 - nosilleg
@frequent:是的,只使用 HTML 图像标签可能会更容易一些。 - Limey
3个回答

2
请在 <cfimage> 标签中指定 quality 属性。我不确定它是否适用于 action="writeToBrowser",但应该可以使用。否则,请提交错误报告。
调整大小和压缩是不同的事情。 :)
请参见:为什么在Coldfusion中调整图像大小,文件大小不会减小,而且图像质量会受到影响? 更新 好消息,有一种未经记录的方法可以让它工作!请参见:http://www.bennadel.com/blog/2405-Using-The-Quality-Attribute-With-The-CFImage-WriteToBrowser-Action.htm
<!--- Write out as a JPG at 20% (using "quality" attribute). --->
<cfimage
    action="writeToBrowser"
    source="#png#"
    format="jpg"
    quality=".2"
    />

你找到了我的另一个问题 :-) 我仍在与这个问题作斗争... - frequent
哦,我不知道你还在为那个问题苦恼。为什么你要再问同样的问题呢?调整“quality”属性对你没有起作用吗? - Henry
没用。不确定是因为 writeToBrowser,但图片大小没有改变一点。我仍然有一些客户给我设置庞大的图片来展示我的产品搜索,所以我需要一些缩小图片到缩略图(200像素宽)和详细视图(600像素宽)的方法。 - frequent
1
@frequent 可能是因为 quality 属性与 writeToBrowser 不兼容。您可以先尝试使用 action=write 设置 quality 属性,将压缩文件写入磁盘(如果您使用的是 CF9+,也可以写入 ram://),然后使用指向该文件路径的 writeToBrowser 方法。最后清理临时文件即可。 :) - Henry
CF8很不幸,但我会尝试一下。需要出发了...开车3小时后再回来,再试一次。如果你想看看我今天烦恼的另一个问题...谢谢! - frequent
请在此处提交增强请求:https://bugbase.adobe.com/ :) - Henry

1

调整图像大小并不意味着要减小文件大小。它是为了通过高度和宽度使其变小。是的,通常情况下,图像文件大小确实会变小。但这种大小缩小取决于源图像。

您可能希望将格式声明为png,因为这可能有助于缩小文件。

另外,为什么要在cfimage标签中包装cfxml?这是一个无用的步骤,会导致额外的处理和膨胀。

因为我需要临时文件的URL/路径请参见此处 - frequent
那么我可以跳过使用CFimage进行调整大小,而只需通过CSS设置尺寸。这意味着我可以跳过cfxml部分,因为不需要临时文件。但我仍然这样做,因为有些人使用系统,他们为我提供了5MB的图像。因此,我需要一些手段来获取该图像并制作400px宽加800px宽的版本,以便在系统中使用,而不是提供的5MB img。 - frequent
通过CSS设置尺寸是一个不好的想法。那样不会对图像大小产生任何影响。而且,当改变大小时,你将有保持纵横比的问题。即使图像大小略有差异,最好在服务器上调整大小。此外,我认为你可以使用cfsavecontent来获取图像路径。由于没有XML开销,这应该更快。 - Dave Ferguson
CSS是出于绝望才使用的...你所说的“在服务器上调整大小”是什么意思?我以为cfimage就是“在服务器上调整大小”的 :-) - frequent
jpeg(有损)可压缩比png(无损)更多,尤其是对于照片。只需要在cfimage中使用quality属性打开压缩即可,就像我在下面的答案中所说的那样。 - Henry

1

使用“action =”writetobrowser“”将使用源图像的副本。它创建一个临时文件,推送到浏览器并稍后销毁。

这是CF 8文档中的一句话:

“使用writeToBrowser操作直接向浏览器显示一个或多个ColdFusion图像,而无需将它们写入文件。”

我使用CF8测试了您的代码,并使用大型照片(4608x3456)@ 3.47MB。在我的浏览器上显示的图像被调整为400x300 @ 247.47KB。我使用Firefox右键单击|查看图像信息来获取调整大小的图像信息。您还可以使用Firebug | Net选项卡获取传输的图像大小。

调整大小后的图像将位于“/ CFFileServlet / _cf_image /”中。

原始文件的大小(#bildpfad##bilddateiname#)不会更改。

不要依赖于旨在是临时的文件的存在。临时意味着仅此而已。即使是相同的源图像,在10分钟后进行调整大小时,一个调整大小的文件名可能与另一个调整大小的文件名不同。不同版本的CF可能会以不同的方式处理临时文件。

如果您需要保留调整大小后的图像副本,请使用action="write"或action="resize",并使用destination属性在CF服务器上保存调整大小后的图像副本。

以下是一个示例,说明如何操作:

<!---assume that bildpfad can be different domains/folders--->
<!---RegEx = remove protocol, replace '/' with '!',  replace '.' with '~'--->
<cfset slashReplacement = "!">
<cfset periodReplacement = "~">
<cfset imageFilename = REReplace(REReplace(REReplaceNoCase(bildpfad, "https?://", "", "one"), "\/", slashReplacement, "all"), "\.", periodReplacement, "all") & bilddateiname>
<!---resizedImgDestination is a web path--->
<cfset resizedImgDestination = "/images/resized/rs_#imageFilename#">
<!---debug info, can comment out when working--->
<cfoutput>source = [#bildpfad##bilddateiname#]<br />destination = [#ExpandPath(resizedImgDestination)#]<br /></cfoutput>
<!---/debug info, can comment out when working--->
<cfif NOT FileExists(ExpandPath(resizedImgDestination))>
    <cfhttp url="#bildpfad##bilddateiname#" result="stGetImg" resolveurl="no" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1" timeout="45" getasbinary="yes" throwonerror="no" />
    <cfset myImage = ImageNew(stGetImg.FileContent)>
    <cfif IsImage(myImage)>
        <cfimage action="resize" destination="#ExpandPath(resizedImgDestination)#" height="" isbase64="false" overwrite="true" source="#myImage#" width="400" />
    </cfif>
</cfif>
<cfoutput><img src="#resizedImgDestination#" /></cfoutput>

通过将高度设置为空字符串,它将按比例调整高度以匹配宽度的大小并进行缩放。
您需要从站点Web根目录创建'/images/resized/'文件夹。
ExpandPath()比使用静态路径定义更好。如果您必须将站点移动到不同的服务器或操作系统,则会节省大量时间。
注意:我更新了上面的代码,以更好地适合问题中的变量使用。我还更改了图像的读取方式。我使用安装了CHF 4 + Hotfixes的CF 8.01,但在读取远程文件时,cfimage出现错误(JPG处理中发生异常。段大小将超出文件流长度)。我的解决方案是使用cfhttp来读取图像。我还更新了代码以使用更好命名的变量“resizedImgDestination”。

首先,感谢提供的信息。我认为我喜欢缓存的想法。我很高兴我的脚本可以使用临时URL/路径,但也认为这不是最好的解决方案。所以你会检查目标文件夹中是否存在图像,如果不存在,你会将图像调整大小并放入目标文件夹吗?如果图像来自另一个服务器,这也适用吗?比如我在www.foo.com上,而图像在www.bar.com/img/上。 - frequent
刚试了一下。在尝试写入目标文件时出现错误。不能确定原因,因为它是通过 AJAX 运行的,而我无法从远程位置设置 CFAdmin 的 AJAX 调试。我会继续尝试解决它。 - frequent
是的,它应该可以工作,因为您只需要检查服务器上调整大小后的文件是否存在。通常,“无法写入目标文件”错误意味着目标路径不正确。由于它被用作AJAX调用,您将看不到我放在其中的调试输出。我建议直接在URL上调用AJAX模块,以查看输出变量。一旦您可以看到destination = []值,您很快就会找出错误所在。 - Scott Jibben
对于第一条评论中的其他问题。是的,您正在检查调整大小图像的目标文件夹,是的,只有在找不到已调整大小的图像时才会调整大小。也就是说,它将缓存调整大小的图像在您的网站上。 - Scott Jibben
我也应该在答案中加入这个。你需要更改此代码片段的前两行才能使其正常工作。 - Scott Jibben
如果您提供变量bildpfad和bilddateiname可能包含的示例,可以创建更好的示例。 不必是实际值,但需要提供一些值的格式来给出一个想法。 - Scott Jibben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接