class JavaImageIOCompare implements Compare {

    public CompareResult compare(DigitalObject first, DigitalObject second,
            List<Parameter> config) {
        // Start timing...
        ServicePerformanceHelper sph = new ServicePerformanceHelper();
        
        // Initialise what will be built:
        List<PropertyComparison> props = new ArrayList<PropertyComparison>();
        ServiceReport sr = null;
        
        // Load the images.
        BufferedImage i1;
        BufferedImage i2;
        try {
            i1 = ImageIO.read( first.getContent().getInputStream() );
            i2 = ImageIO.read( second.getContent().getInputStream() );
        } catch (IOException e) {
            return new CompareResult(null, ServiceUtils.createExceptionErrorReport("IOException reading the images. ", e));
        }
        if( i1 == null || i2 == null ) {
            log.warning("One of the images was null when loaded!");
            return new CompareResult(null, ServiceUtils.createErrorReport("Error reading the images, got a NULL."));
        }
        // Record time take to load the inputs into memory:
        sph.loaded();
        
        // Check comparison is possible: Are the dimensions the same?
        if (i1.getWidth() != i2.getWidth() || i1.getHeight() != i2.getHeight()) {
            // FIXME is this really an error, or rather a 'images are different' result?
            return new CompareResult(null, ServiceUtils.createErrorReport("The image dimensions must match!"));
        }
        // FIXME Check comparison is sensible: are there the same number of channels? This is probably a WARNING?
        if( i1.getColorModel().getNumComponents() != i2.getColorModel().getNumComponents()) {
            System.out.println("The number of colour components does not match. "+i1.getColorModel().getNumComponents()+" != "+i2.getColorModel().getNumComponents());
            log.warning("The number of colour components does not match. "+i1.getColorModel().getNumComponents()+" != "+i2.getColorModel().getNumComponents());
            sr = new ServiceReport(ServiceReport.Type.WARN, ServiceReport.Status.SUCCESS, "Number of colour components was not the same. The missing channels, e.g. the alpha channel, will be assumed to be zero.");
            // FIXME I think this should be more serious, as the results can be rather misleading.
            // The comparison assumes the bit-mask to be zero everywhere, but this did not lead to such a bad PSNR?!
        }

        // Run the comparison:
        double psnr = psnr(i1, i2);
        props.add( buildPsnrProperty(psnr) );
        
        // Create a happy service report if no problems occurred.
        if( sr == null) {
            // Also store some service properties:
            sr = new ServiceReport(ServiceReport.Type.INFO, ServiceReport.Status.SUCCESS, 
                    "Comparison succeeded.", sph.getPerformanceProperties() );
        }
        
        // Halt performance measurement:
        sph.stop();

        // Return the result:
        return new CompareResult( props, sr );
    }

}