Преобразование PNG в JPEG

У меня возникают проблемы с преобразованием простого PNG в формат JPEG. Я использую следующий код:

...

    File png = new File(filePath);
    try {
        SeekableStream s = new FileSeekableStream(png);
        PNGDecodeParam pngParams = new PNGDecodeParam();
        ImageDecoder dec = ImageCodec.createImageDecoder("png", s, pngParams);
        RenderedImage pngImage = dec.decodeAsRenderedImage();
        JPEGEncodeParam jparam = new JPEGEncodeParam();
        jparam.setQuality(0.50f); // e.g. 0.25f
        File jpeg = new File("jpeg.jpeg");
        FileOutputStream out = new FileOutputStream(jpeg);

        ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", out, jparam); 

        encoder.encode(pngImage);

        s.close();

    } catch (IOException e) {
        ok = false;
        e.printStackTrace();
    }

    return ok;
}

...

Я получаю исключение JAI → java.lang.RuntimeException: могут быть записаны только 1 или 3-полосные байтовые данные.   на com.sun.media.jai.codecimpl.JPEGImageEncoder.encode(JPEGImageEncoder.java:148)...

Из вариантов. Любое предложение?

Ответы

Ответ 1

у вас, вероятно, есть альфа-канал в png, который вам нужно избавиться, прежде чем пытаться написать jpg.

Создайте новый BufferedImage с типом TYPE_INT_RGB (не TYPE_INT_ARGB), а затем напишите исходное изображение (pngImage) на новое пустое изображение.

Что-то вроде этого (предупреждение, не проверенный код):

BufferedImage newImage = new BufferedImage( pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newImage.createGraphics().drawImage( pngImage, 0, 0, Color.BLACK, null);

Ответ 2

Возможно, было бы проще использовать ImageIO, чтобы прочитать PNG в BufferedImage и записать изображение в формате JPEG.

Приложение: при таком подходе преобразование обрабатывается прозрачно писателем ImageTranscoder.

BufferedImage img = ImageIO.read(new File("image.png"));
ImageIO.write(img, "jpg", new File("image.jpg"));

Ответ 3

Я также обнаружил, что чтение PNG-изображения в BufferedImage с ImageIO (Java 6) и запись его в название формата JPG исказили изображение. Изображение было там, но цвета выглядели "соляризованными" и почти перевернутыми. Файл JPG был намного меньше, чем PNG файл, поэтому было сделано много сжатия. Я не вижу, как вы можете контролировать сжатие или глубину цвета.

Ответ 4

Я полагаю, что JAI читает изображение PNG с индексированной цветовой моделью и может записывать только 8-битные оттенки серого или 24-битные цветные изображения в виде файлов JPEG.

Если вам не требуется использовать JAI для этой задачи, вы можете использовать ImageIO вместо:

ImageIO.write(ImageIO.read(new File("in.png")), "JPEG", new File("out.jpg"));

Ответ 5

Я получил следующее сообщение в немного другом контексте. Избавление от альфа-канала решает проблему

javax.imageio.IIOException: Sample size must be <= 8
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:435)
    at javax.imageio.ImageWriter.write(ImageWriter.java:580)
    at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriter.write(Unknown Source)
    at net.sf.basedb.util.ImageTools.tiffToJpg(ImageTools.java:98)
    at net.sf.basedb.util.ImageTools.main(ImageTools.java:118)