Search code examples
javaimagejpegjfif

Reading image data from a JFIF?


So I'm reading JFIF (JPEG) data from a file, as an exercise (I know there are libraries out there that already do this, I'm not looking for those). I've already got the image file size, color depth, and dimensions. However, I'm not too sure how to get the actual image data. I've looked at the data in a hex editor, and comparing that against the actual image leads me nowhere. If anyone has a good resource to start on this (I know it's probably an arduous and enlightening process, but that's why I'm doing it), that would be awesome.

My code so far, just for context:

// check header data, assign header data to important fields

        // Start Of Image (SOI) must be FFD8 and the next marker must be FF
        if(!(this.data[0] == (byte) 0xFF && this.data[1] == (byte) 0xD8
                && this.data[2] == (byte) 0xFF))
            this.isValid = false;

        // check if file is not valid
        if(!isValid) 
            log.log(Level.SEVERE, 
                    String.format("ERROR: File %s is not registered as a JFIF!\n", this.filename), 
                    new IllegalArgumentException());

        // If the next values are correct, then the data stream starts at SOI
        // If not, the data stream is raw
        this.isRawDataStream = !(this.data[3] == (byte) 0xE0
                && this.data[6]  == (byte) 0x4A
                && this.data[7]  == (byte) 0x46
                && this.data[8]  == (byte) 0x49
                && this.data[9]  == (byte) 0x46
                && this.data[10] == (byte) 0x00);

        // Read until SOF0 marker (0xC0)
        int i = 11;
        while(this.data[i] != (byte) 0xC0) {
            i++;
        }
        System.out.println("SOF0 marker at offset " + i);

        // Skip two bytes, next byte is the color depth
        this.colorDepth = this.data[i+3];

        // Next two bytes are the image height
        String h = String.format("%02X", this.data[i+4]) + String.format("%02X", this.data[i+5]);
        this.height = hexStringToInt(h);
        System.out.println("Height: " + this.height);

        // Next two bytes are the image width
        String w = String.format("%02X", this.data[i+6]) + String.format("%02X", this.data[i+7]); 
        this.width = hexStringToInt(w);
        System.out.println("Width: " + this.width);

        System.out.println("Color depth: " + this.colorDepth);
        // load pixels into an image
        this.image = new BufferedImage(this.width,
                                       this.height, 
                                       BufferedImage.TYPE_INT_RGB);

Then, I need to get each pixel and send it to the image. How would I get each pixel and its respective RGB data?


Solution

  • What you are trying to do is not a simple afternoon project. This book explains the process: There is A LOT of code between JPEG compressed data and pixel values.

    http://www.amazon.com/Compressed-Image-File-Formats-JPEG/dp/0201604434/ref=pd_bxgy_b_img_y

    First of all, you have to deal with two separate but related compression methods: Sequential and progressive.

    As you read the bit data, you have to

    1. Huffman decode
    2. Run length decode
    3. Inverse Quantization
    4. List item
    5. Inverse Discrete Cosine Transform
    6. Up sample
    7. YCbCr to RGB convert

    That's in the simple case of sequential.

    You are not going to get all of those steps explained on this forum.

    I also recommend

    http://www.amazon.com/dp/1558514341/ref=rdr_ext_tmb