3

Possible Duplicate:
Why should I resize an image in Coldfusion if the file size doen't decrease and the quality of the image suffers?

I must be doing something wrong here... using Coldfuison8

I have a product search which is pulling in images from external servers, so I need to set images on runtime.

Say I have a jpg 500x500px 111kb, which I'm grabbing from the external server.

Right now I'm doing this:

<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>

This displays the image allright, but when I check the filesize, I have

400x400px 111.2kB

If I use IrfanView for example and just reduce the filesize and save the image, I'm already at 65kb.

Question: How can I make CFIMAGE reduce the file size if I'm resizing the image? If the size stays at 111kb, why use CFIMAGE at all and not simply add the image as plain HTML.

**EDIT'':
The variables Bildpfad and Bilddateiname will be something like:

bildpfad (path to image):         http://www.some-server.com/images/
bilddateiname (filename):         some_image123.jpg
Community
  • 1
  • 1
frequent
  • 27,643
  • 59
  • 181
  • 333

3 Answers3

2

Specify the quality attribute in <cfimage>. I'm not sure if it works with action="writeToBrowser", but it should. Otherwise, file a bug report.

Resize and Compression are different things. :)

See: Why should I resize an image in Coldfusion if the file size doen't decrease and the quality of the image suffers?

UPDATE

Good news, there's an undocumented way to get it working! See: 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"
    />
Community
  • 1
  • 1
Henry
  • 32,689
  • 19
  • 120
  • 221
  • You found my other question :-) I'm still fighting with this... – frequent Jul 13 '12 at 16:54
  • oh, didn't know you're still struggling with that. Why do you ask the same question again? Adjusting `quality` attribute didn't work for you?? – Henry Jul 13 '12 at 17:12
  • Didn't work. Not sure if because of writeToBrowser, but the image size didn't change a bit. I still have some clients setting gigantic images for me to pick up to display in my product search, so I need some means of downsizing the images to thumbnail (200px width) and detail view (600px width) – frequent Jul 13 '12 at 17:21
  • 1
    @frequent it could be because `quality` attribute doesn't work with `writeToBrowser`. You can try setting `quality` attribute with `action=write` first, and write the compressed file to disk (or `ram://` if u're using CF9+), then `writeToBrowser` with path to that file. Then clean up afterwards. :) – Henry Jul 13 '12 at 17:24
  • CF8 unfortunately, but I will give it a try. Need to go.. 3hrs drive then check back and give it another try. If you want to check out my other [question](http://stackoverflow.com/questions/11475148/is-it-a-good-idea-to-store-and-access-an-active-query-resultset-in-coldfusion-vs) bugging me today... THANKS! – frequent Jul 13 '12 at 17:27
  • File the enhancement request here: https://bugbase.adobe.com/ :) – Henry Jul 13 '12 at 17:39
1

Resizing an image it not intended to make the file size smaller in bytes. It is to make it smaller by height and width. Yes, more often than not the image file size does become smaller. But that size reduction depends on the source image.

You might want to declare the format as png as that may help make the file smaller.

Also, why are you wrapping the cfimage tag in cfxml? That is a useless step that is causing extra processing and bloat.

Dave Ferguson
  • 743
  • 3
  • 10
  • Because I need the temp file URL/path [see here](http://www.bennadel.com/blog/1890-Getting-The-Image-SRC-Of-ColdFusion-s-CFImage-WriteToBrowser-Temporary-Image-With-CFXML.htm) – frequent Jul 13 '12 at 15:47
  • So then I can just skip the resize using CFimage and just do set the dimensions via CSS. Would mean I could skip the cfxml part, too, because there would be no temp file. Still I'm doing this, because there are some people using the system, which set 5MB images for me to pick up. So I need some means of grabing that image and making a 400px wide plus 800px wide version for me to use in the system instead of a supplied 5MB img – frequent Jul 13 '12 at 15:51
  • Setting the dimensions via css is a bad idea. That will have no affect on image size at all. Also, you will have issues trying to maintain aspect ratio when altering the size. You are best to resize in the server even if there is a slight disparity in image size. Also, I think you can use cfsavecontent to get the image path. This should be faster as there is no xml overhead. – Dave Ferguson Jul 13 '12 at 16:00
  • CSS was out of despair... what do you mean by "resize in the server"? I thought cfimage was "resize in the server" :-) – frequent Jul 13 '12 at 16:10
  • jpeg (lossy) can be compressed Much more that png (lossless) especially for photos. It's just the matter of turning on compression in cfimage using `quality` attribute, like I said in my answer below. – Henry Jul 13 '12 at 17:27
1

The use of 'action="writetobrowser"' will use a copy of the source image. It creates a temporary file that is pushed to the browser and destroyed later.

Here is a phrase from the CF 8 docs:

"Use the writeToBrowser action to display one or more ColdFusion images directly to the browser without writing them to files."

I tested your code with CF8 with a large photo (4608x3456) @ 3.47MB. The image that was displayed on my browser was resized to 400x300 @ 247.47KB. I used the Firefox right-click | View Image Info to get the resized image info. You can also use the Firebug | Net tab to get the transmitted image size.

The resized image will be in "/CFFileServlet/_cf_image/".

The size of the original file (#bildpfad##bilddateiname#) will not change.

Don't rely on the existence of a file that is designed to be temporary. Temporary means just that. The file name from one resize may not be the same filename on a resize 10 minutes later even though it is the same source image. Temporary files may be handled differently between different versions of CF as well.

If you need to keep a copy of the resized image, use action="write" or action="resize" with a destination attribute and save a copy of the resized image on the CF server.

Here is a sample of how it could work:

<!---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>

By leaving height as an empty string, it will resize and scale the height to match the width proportionally.

You will have to create '/images/resized/' folder from your sites web root.

ExpandPath() is better than using static path definitions. If you ever have to move a site to a different server or OS it will save a lot of time.

Note: I updated the code above to better fit the use of the variables in the question. I also changed how the image was read. I have CF 8.01 with CHF 4 + Hotfixes installed, but I got an error (Exception occured in JPG processing. segment size would extend beyond file stream length) with cfimage when reading remote files. My solution was to use cfhttp to read the image instead. I also updated the code to use a better named variable "resizedImgDestination".

Scott Jibben
  • 2,229
  • 1
  • 14
  • 22
  • First up. Thanks for info. I think I like the caching idea. I was happy my script worked with temp url/paths, but also thought this wasn*t the best of solutions. So you are checking in the destination folder, whether an images exists and if not, you take the image and resize to destination folder? Will this also work if the images are coming from another server? Say I'm on www.foo.com and the image is in www.bar.com/img/ – frequent Jul 13 '12 at 21:45
  • Just tried this real quick. I'm getting an error when trying to write to the destination file. Can't really say why, because it's running through AJAX and I can't set AJAX debugging in CFAdmin from remote location. I'll keep playing with it – frequent Jul 14 '12 at 06:52
  • Yes, it should work because you would only be checking for the existence of the resized file on your server. Usually the error that says "can't write destination file" means that the destination path is incorrect. Since it is being used as an AJAX call, you won't see the debug output that I put in there. I would suggest calling the AJAX module directly on a URL to see what the output variables are. Once you can see the destination = [] value, you'll figure out pretty quickly where the error is. – Scott Jibben Jul 14 '12 at 08:38
  • For the other questions in the first comment. yes, you are checking the destination folder of the resized images and yes it should only resize if the resized image is not found. That is, it will cache the resized images on your web site. – Scott Jibben Jul 14 '12 at 08:41
  • I should have added this to the answer as well. You will have to change the first two lines of code in this snippet to get it to work. – Scott Jibben Jul 14 '12 at 08:44
  • If you provide samples of what the variables: bildpfad and bilddateiname could contain, a better example could be created. Doesn't have to be real values, but something to give an idea of the format of the values is. – Scott Jibben Jul 14 '12 at 08:53