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:
- Grab an instance of a JPEG writer
- Initialize the image parameters and output settings
- Extract the underlying BufferedImage from the CF image object
- 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.