You are not logged in.

#1 2012-08-30 20:16:59

sammystag
Member

Fix for JPEG length calculation

Hi,

I can see a few people have had the same problem as me when loading certain JPEGs.  If they contain 0xFF 0xD9 anywhere before end of the file then the length is calculated incorrectly resulting in a crash.  Anyway I did a bit of searching and the following change to a function in GRRLIB_texEdit.c should fix the problem (works for me at least).  In short you need to skip over data following certain markers in the image.  The number of bytes to skip is given by the two bytes following the marker and this number includes those two bytes.

Code:

/**
 * Load a texture from a buffer.
 * Take care to have the JPG finish with 0xFF 0xD9!
 * @param my_jpg The JPEG buffer to load.
 * @return A GRRLIB_texImg structure filled with image information.
 */
GRRLIB_texImg*  GRRLIB_LoadTextureJPG (const u8 *my_jpg) {
    int n = 0;

    if ((my_jpg[0]==0xFF) && (my_jpg[1]==0xD8) && (my_jpg[2]==0xFF)) {
        while(true) {
            
            // marker starts with 0xFF and may be padded at the start with any number of additional FFs     
            while (my_jpg[n]==0xFF) {
                ++n;
            }
            
            // Need to look at the next byte to see what kind of marker this is.
            // It may be:
            // (A) End marker
            // (B) Marker with no data following it
            // (C) Any other marker will be followed by a length specifier from which we will determine how many bytes to skip
            if (my_jpg[n] == 0xD9) {
                // We have found the end of the JPEG.
                // increment n as the length of the data, including this byte, is the current index + 1
                ++n; 
                break;
            } else if (my_jpg[n] == 0x01 || (my_jpg[n] >= 0xD0 && my_jpg[n] <= 0xD8)) {
                // Certain markers are not followed by any data and so do not have a length specifier.
                // Just move onto the next byte (which should be 0xFF)
                ++n;
            } else {
                // Read the next two bytes to get the length specifier.
                // This length includes the two bytes for the length specifier
                ++n;
                int skip = 256 * my_jpg[n] + my_jpg[n+1];
                n += skip;
            }
            
            // We may now have some entropy encoded data.
            // We want to skip this and get to the next marker.
            // Within the entropy encoded data any 0xFF will be followed
            // by a 0x00 to flag that this is not a marker.
            // Just skip forward until we find a marker - i.e. 0xFF not followed by 0x00.
            // When we find a marker we are ready to start the loop again.
            while (my_jpg[n]!=0xFF || my_jpg[n+1]==0x00) {
                ++n;
            }
        }
    }
    return GRRLIB_LoadTextureJPGEx(my_jpg, n);
}

An example of an image that fails without the change is toddtris\images\ttbg.jpg in http://www.themightystags.com/toddtris_ … ris1.0.zip .

Cheers,

Sammy

Last edited by sammystag (2012-08-30 20:19:27)

Offline

 

Board footer

Powered by FluxBB