Using pure JS to retrieve image orientation failing in one test case

I'm a server side dev learning the ropes of pure JS these days. One practical example I'm working through is image processing. This question is about my endeavour to retrieve image orientation information in order to subsequently rotate and/or reflect it.

This excellent SO answer got me started. The code I've written is:

// used to determine orientation information
function get_orientation(file, callback) {
  var reader = new FileReader();
  reader.onload = function(e) {
    var view = new DataView(e.target.result);
    if (view.getUint16(0, false) != 0xFFD8) return callback(-2);
    var length = view.byteLength, offset = 2;
    while (offset < length) {
      var marker = view.getUint16(offset, false);
      offset += 2;
      if (marker == 0xFFE1) {
        if (view.getUint32(offset += 2, false) != 0x45786966) return callback(-1);
        var little = view.getUint16(offset += 6, false) == 0x4949;
        offset += view.getUint32(offset + 4, little);
        var tags = view.getUint16(offset, little);
        offset += 2;
        for (var i = 0; i < tags; i++)
          if (view.getUint16(offset + (i * 12), little) == 0x0112)
            return callback(view.getUint16(offset + (i * 12) + 8, little));
      }
      else if ((marker & 0xFF00) != 0xFF00) break;
      else offset += view.getUint16(offset, false);
    }
    return callback(-1);
  };
  reader.readAsArrayBuffer(file.slice(0, 128 * 1024));
}

This works fine for a range of images, however here's one image that causes the line var tags = view.getUint16(offset, little); to crash with RangeError: argument 1 accesses an index that is out of range.

I can't tell whether the image is corrupt, or whether the code needs more specialization. Can an expert help me with tweaking this in order to handle cases like these? Thanks in advance!

Answers:

Answer

That image has an Exif block, but it is empty.

$ exif -x 28531470-85e0855a-70c9-11e7-9bba-107a664e6635.jpeg 
<exif>
</exif>

Here is a partial hex dump,

00000010: 0001 0000 ffe1 0008 4578 6966 0000 ffdb  ........Exif....

When it adjusts the offset with view.getUint32() it is using quantization data from the ffdb block.

You could try reading the marker length, and skip if it is <= 8,

while (offset < length) {
  var marker = view.getUint16(offset, false);
  var markerLength = view.getUint16(offset+2, false);
  ....

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.