Recently, I was doing some work on an internal system where I was doing some image processing. I was taking uploaded images and resizing them into a smaller preview image on request. The code for this is quite simple.

view plain print about
1<cfimage action="read" source="testimg.png" name="myImg">
2<cfimage action="resize" height="150" source="#myImg#" width="150">
3<cfimage action="writeToBrowser" source="#myImg#">

However, when running the code it was taking between 30-60 seconds to run. I tried a bunch of different things to get it to work correctly. I even rewrote it in cfscript to see if that would help. Well, it didn't, no difference. The processing till took forever.

At this point I opened up the ColdFusion server monitor. The monitor will allow me to see what the request is actually getting stuck on. With the monitor running I ran the code again a few times. Once normal, and another with the image resize code commented out. The monitor showed me that the code was indeed getting stuck on the resize.

I then started looking at the source images. The images were all under 1mb so size issue was now out. On a whim I ran a test using a jpg image. This time the image processed immediately. Returned in under a second and resized as expected.

Knowing that jpgs worked I then started looking at details of the png images. I created a sample png using fireworks. This sample image processed just as quick as the jpg test. I then checked the image info on a failing png to the info on the png that just worked. I noticed that the failing png had no alpha_channel_support and the transparency was set to opaque. There were other differences but those were the 2 major ones.

view plain print about
1colormodel:
2    [struct]
3    alpha_channel_support: NO
4    alpha_premultiplied: NO
5    bits_component_1: 8
6    bits_component_2: 8
7    bits_component_3: 8
8    colormodel_type: ComponentColorModel
9    colorspace: Any of the family of RGB color spaces
10    num_color_components: 3
11    num_components: 3
12    pixel_size: 24
13    transparency: OPAQUE
14height: 345
15source: D:\Inetpub\wwwroot\tests\testimg1.png
16width: 516
17
18
19colormodel:
20    [struct]
21    alpha_channel_support: YES
22    alpha_premultiplied: NO
23    bits_component_1: 8
24    bits_component_2: 8
25    bits_component_3: 8
26    bits_component_4: 8
27    colormodel_type: ComponentColorModel
28    colorspace: Any of the family of RGB color spaces
29    num_color_components: 3
30    num_components: 4
31    pixel_size: 32
32    transparency: TRANSLUCENT
33height: 400
34source: D:\Inetpub\wwwroot\tests\testimg2.png

I knew that the suspect png images were all created as screenshots from a mac. So, I created a new one using this method and ran another test. This image did in fact have the same long processing issue. So, now I know it is truly the source image causing the problem. Now, the hard part, finding a way to work around it.

I asked a few people if they knew of this issue and if they had a way around it. In the responses that I received people mentioned that they remembered this being an issue in ColdFusion 8 as well. It was suggested by Jeff Coughlin that a work around would be to basically change the file from a png to a jpg. This could be accomplished by reading the image, writing it back as a jpg, and reading in the jpg.

Since I am dealing with ColdFusion 9 this would be a great time to use the virtual file system. This should speed things up considerably. In the end I ended up with this code.

view plain print about
1<cfscript>
2    newName = '#randRange(11111,99999)#.jpg';
3    myImg = imageRead ("#expandPath('.')#/testimg.png");
4    imageWrite (myImg,'ram://#newName#',1, true);
5
    
6    myImg = imageRead("
ram://#newname#");
7
    imageScaleTofit (myImg,250,250);
8    fileDelete ("ram://#newName#");    
9
</cfscript>
10<cfimage action="
writeToBrowser" source="#myImg#">

It was also suggested that I could remove the native image handling in ColdFusion to correct it. The details on this were unavailable so I am a little skeptical on actually doing this. However, of some details on how I could perform this surface I would be willing to give it a try.

Till next time...

--Dave