--!movie
--****************************************************************************
-- @file JPEG EXIF orientation data extractor
-- @author Valentin Schmidt
-- @version 0.2
--
-- Usage:
-- res = getOrientation(_movie.path&"test.jpg")
-- put "Orientation:" && res
--****************************************************************************
----------------------------------------
-- Extracts orientation from JPEG file
-- @param {string} jpgFile - path to JPEG file
-- @return {integer} - orientation as positive number 1..8, or negative error code
----------------------------------------
on getOrientation (jpgFile)
ba = _fileGetBytes(jpgFile)
if ilk(ba)<>#bytearray then return -3
return getOrientationFromData(ba)
end
----------------------------------------
-- Extracts orientation from JPEG data passed as byteArray
-- @param {byteArray} ba - the JPEG data
-- @return {integer} - orientation as positive number 1..8, or negative error code
----------------------------------------
on getOrientationFromData (ba)
if _getUint16(ba, 0, FALSE) <> 65496 then return -2
len = ba.length
offset = 2
repeat while (offset < len)
if _getUint16(ba, offset+2, FALSE) <= 8 then return -1
marker = _getUint16(ba, offset, FALSE)
offset = offset + 2
if (marker = 65505) then
offset = offset + 2
if _getUint32(ba, offset, FALSE) <> 1165519206 then return -1
offset = offset + 6
little = _getUint16(ba, offset, FALSE) = 18761
offset = offset + _getUint16(ba, offset + 4, little)
tags = _getUint16(ba, offset, little)
offset = offset + 2
repeat with i = 1 to tags
if _getUint16(ba, offset + (i * 12), little) = 274 then
return _getUint16(ba, offset + (i * 12) + 8, little)
end if
end repeat
else if bitAnd(marker, 65280) <> 65280 then
exit repeat
else
offset = offset + _getUint16(ba, offset, FALSE)
end if
end repeat
return -1
end
----------------------------------------
-- Reads whole file, returns byteArray
-- @param {string} fn
-- @return {bytearray|FALSE}
-- @private
----------------------------------------
on _fileGetBytes (fn)
fp = xtra("fileIO").new()
fp.openFile(fn, 1)
if fp.status()<>0 then return FALSE
data = fp.readByteArray(fp.getLength())
fp.closeFile()
return data
end
----------------------------------------
-- @private
----------------------------------------
on _getUint16 (ba, pos, littleEndian)
if littleEndian then
return ba[pos+1] + 256*ba[pos+2]
else
return 256*ba[pos+1] + ba[pos+2]
end if
end
----------------------------------------
-- Returns float, to overcome Director's signed int limit (the maxInteger)
-- @private
----------------------------------------
on _getUint32 (ba, pos, littleEndian)
if littleEndian then
return ba[pos+1] + 256*ba[pos+2] + 65536*ba[pos+3] + 16777216.*ba[pos+4]
else
return 16777216.*ba[pos+1] + 65536*ba[pos+2] + 256*ba[pos+3] + ba[pos+4]
end if
end