JDK-8041501 : ImageIO reader is not capable of reading JPEGs without JFIF header
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 7u45,8,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • Submitted: 2013-12-26
  • Updated: 2020-08-14
  • Resolved: 2015-12-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u101Fixed 9 b100Fixed
Related Reports
Duplicate :  
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
This bug:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4776576

seems to describe what's happening in 1.7.0_45 again.

  To see the output:
http://stackoverflow.com/questions/20789043/image-changes-color-when-saved-with-java


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.imageio.ImageIO;


public class ImageSaver {
    
    public static void main(final String url) {
        URL u = null;
        try {
            u = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        String file = url.substring(url.indexOf("//") + 2);
        Path filePath = Paths.get("c:/").resolve(file);
        try {
            Files.createDirectories(filePath.getParent());
            BufferedImage img = ImageIO.read(u);
            ImageIO.write(img, "jpg", filePath.toFile());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
q&d:

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.imageio.ImageIO;


public class ImageSaverWorkAround {
    
    public static void main(final String url) {
        URL u = null;
        try {
            u = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        String file = url.substring(url.indexOf("//") + 2);
        Path filePath = Paths.get("c:/").resolve(file);
        try {
            Files.createDirectories(filePath.getParent());
            Image img = Toolkit.getDefaultToolkit().createImage(url);
            while (img.getWidth(null) == -1 || img.getHeight(null) == -1) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int w = img.getWidth(null);
            int h = img.getHeight(null);
            int type = BufferedImage.TYPE_INT_RGB;
            BufferedImage pic = new BufferedImage(w, h, type);
            Graphics2D g2 = pic.createGraphics();
            g2.drawImage(img, 0, 0, null);
            g2.dispose();
            ImageIO.write(pic, "jpg", filePath.toFile());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Comments
Code change is done review is in progress.
23-11-2015

In case of 4 channel images there is no need to add any extra checks. There is no condition which determines jpeg_color_space as CMYK in IJG library. So in imageioJPEG.c we are just checking for sampling factor and changing color space we are not overwriting decision made in IJG library.
20-11-2015

In imageioJPEG.c when there is no JFIF & EXIF marker present we are just checking for sampling factor and changing color space. This is overriding decision made in jdapimin.c where we check for component ID's to determine colorspace. in imageioJPEG.c we should check for component ID's and if its not there then only we should determine colorspace based on sampling factors. Have to add extra checks in imageioJPEG.c
20-11-2015