3

I am using ColdFusion's <cfimage> to resize images and then save as #imagename#.jpg on the server.

I can see options to specify quality but I can't see anything to save the jpg as progressive or even optimised. I would like progressive because it gives a perceived impression of quicker loading on the page.

Is it possible to do this?

James A Mohler
  • 11,060
  • 15
  • 46
  • 72
volume one
  • 6,800
  • 13
  • 67
  • 146
  • 1
    This makes me wonder what is underlying image library behind `` and can any of its functionality be tapped directly. This page lists lots of tools, but I don't know if any are used. http://stackoverflow.com/questions/2407113/open-source-image-processing-lib-in-java – James A Mohler Dec 09 '15 at 16:31
  • @JamesAMohler - Last I checked it was JAI, which did not support progressive jpg's, but .. that was a while ago. It may have changed. [This thread](http://stackoverflow.com/questions/10976936/how-to-create-a-progressive-jpeg-image-on-android) suggests it *might* be supported in later versions. – Leigh Dec 09 '15 at 18:06
  • Tried it out and it seems to work, but I am not sure how one would test it. – Leigh Dec 10 '15 at 17:24
  • I don't see anything in the documentation either. One of the problems for an encoder with progressive JPEG is how to specify the number of scans and breakdown of those scans.I suspect many developers just say &)*&)* it. – user3344003 Dec 10 '15 at 22:23
  • @user3344003 - Heh, I was just reading up on the "innards" of jpegs and was wondering about scans. I suspect you are right that most folks just say - the defaults are good enough for me. – Leigh Dec 11 '15 at 09:30
  • If you want to know the innards of JPEG, the book to get is http://www.amazon.com/Compressed-Image-File-Formats-JPEG/dp/0201604434/ref=sr_1_2?ie=UTF8&qid=1449861380&sr=8-2 – user3344003 Dec 11 '15 at 19:17

1 Answers1

2

CFImage does not support writing progressive jpegs out of the box. From what I have read, it is supported in java to some extent. However, it is a big topic. So this is by no means a complete answer, just a starting point.

Java

My knowledge of the jpeg format is pretty rudimentary, but creating a basic progressive jpeg in java seemed pretty straight-forward:

  1. Grab an instance of a JPEG writer
  2. Initialize the image parameters and output settings
  3. Extract the underlying BufferedImage from the CF image object
  4. Write the new jpeg to disk

One way to see it action, is by using Fiddler2 to simulate a slow connection. Under Rules > Performance, select "Simulate Modem speeds" and "Disable Caching".

Example:

    // Create your CF image object 
    yourCFImage = imageNew("c:\path\input.jpg"); 

    // ... resizing and other stuff 

    // Grab a JPEG writer. Validation omitted for brevity
    // In real code, verify writer exists and progressives is supported first
    // ie jpegWriters.hasNext() and imageParam.canWriteProgressive()
    ImageIO = createObject("java", "javax.imageio.ImageIO");
    jpegWriters = ImageIO.getImageWritersByFormatName("jpg");
    writer = jpegWriters.next();
    imageParam = writer.getDefaultWriteParam();

    // Where to save new image on disk
    destinationFile = createObject("java", "java.io.File").init( "c:\path\outut.jpg" );
    destinationStream = ImageIO.createImageOutputStream( destinationFile );

    // Parameters for desired image quality and interlacing
    // NB: Compression type support varies (JPEG-LS, ...)
    // Check availability with getCompressionType()
    writer.setOutput( destinationStream );
    imageParams = writer.getDefaultWriteParam();
    imageParams.setCompressionMode( imageParams.MODE_EXPLICIT);
    imageParams.setCompressionQuality( javacast("float", 0.80) ); // 80%
    imageParams.setProgressiveMode( imageParams.MODE_DEFAULT );

    // Write the new image to disk
    buffImage = ImageGetBufferedImage( yourCFImage );
    IIOImage = createObject("java", "javax.imageio.IIOImage");
    imageToSave = IIOImage.init( buffImage, javacast("null", ""), javacast("null", ""));
    writer.write( javacast("null", ""), imageToSave, imageParams );

    // Cleanup object
    destinationStream.flush(); 
    destinationStream.close(); 
    writer.dispose(); 

External Tools

Another option is use cfexecute with an external tool like jpegtran or ImageMagic. Both support progressive jpegs and additional options for customization. For example, jpegtran supports customization though scan files, which offer a lot of control. (Unfortunately, I have not quite wrapped my head around those yet...). Try it out with the default settings first. Those may be good enough for your purposes.

<cfexecute name="C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe" 
    arguments=" -interlace line -quality 85 c:\path\source.jpg c:\path\output.jpg" 
    ... 
 >

As an aside, I came across an interesting tool while researching: JSK (JPEG Scan Killer). It is not used to create progressive jpegs, but it really helps explain how they are generated and where scanning fits into the process.

Community
  • 1
  • 1
Leigh
  • 28,765
  • 10
  • 55
  • 103