Replacing deprecated Sun packages Converting Tiff To Jpeg

1k views Asked by At

We have an old piece of code, which still uses Sun JAI Apis to create a jpeg from a tiff file

 private File createJPEG(String tifFilePath){

    FileOutputStream fos = null;
    SeekableStream s = null;

    try {

      s = new FileSeekableStream(tifFilePath);
      TIFFDecodeParam param = null;
      ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);
      RenderedImage op = dec.decodeAsRenderedImage(0);

      File jpgFile = new File(tifFilePath.replace("tif","jpg"));
      fos = new FileOutputStream(jpgFile);

      JPEGEncodeParam jpgparam = new JPEGEncodeParam();
      jpgparam.setQuality(67);

      ImageEncoder en = ImageCodec.createImageEncoder("jpeg", fos, jpgparam);
      en.encode(op);
      fos.flush();
    }catch (IOException ex){
      LOGGER.error(ex);
    }finally {
      if(fos != null) {
        try {
          fos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if(s != null){
        try {
          s.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return null;
  }

Now this doesn't work anymore an a system with a newer Java version, I get the error noclassdeffounderror com/sun/image/codec/jpeg/jpegcodec when running this code.

These are the imports:

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;
import com.sun.media.jai.codec.SeekableStream;
import com.sun.media.jai.codec.TIFFDecodeParam;
import com.sun.media.jai.codec.TIFFEncodeParam;

Now I understand that you shouldn't use com.sun packages anymore and this error which I am getting is because JPEGCodec doesn't exist anymore on the Java Runtime we use in the new system. But how can I replace these imports?

1

There are 1 answers

0
Harald K On

The above code should be fairly simple to port to ImageIO directly.

I've kept the variable names as far as I found reasonable, to make it easier to understand, and rewritten to use try-with-resources. I believe this should work:

private File createJPEG(String tifFilePath) {
    try (ImageInputStream s = ImageIO.createImageInputStream(new File(tifFilePath))) {
        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("TIFF"); // Could also use ImageIO.getImageReaders(s) to support any input format
        if (!readers.hasNext()) {
            return null; // ...or throw new IllegalArgumentException or similar
        }

        ImageReader dec = readers.next();
        dec.setInput(s);

        // The above code doesn't seem to use param, but if needed that is also possible
        ImageReadParam param = null; // dec.getDefaultReadParam() or new TIFFImageReadParam()
        RenderedImage op = dec.readAsRenderedImage(0, param); // Could als use dec.read(0, param) in most cases 
        
        File jpgFile = new File(tifFilePath.replace("tif", "jpg"));

        try (ImageOutputStream fos = ImageIO.createImageOutputStream(jpgFile)) {
            JPEGImageWriteParam jpgparam = new JPEGImageWriteParam(Locale.getDefault());
            jpgparam.setCompressionMode(MODE_EXPLICIT);
            jpgparam.setCompressionQuality(0.67f); // You might want to tune this parameter to get same quality/compression ratio as JAI

            ImageWriter en = ImageIO.getImageWritersByFormatName("JPEG").next();
            en.setOutput(fos);
            en.write(null, new IIOImage(op, null, null), jpgparam);
        }
    } catch (IOException ex) {
        LOGGER.error(ex);
    }

    return null; // What the original code does, probably you want to return jpgFile?
}