1. --!movie
  2.  
  3. --****************************************************************************
  4. -- @file JPEG EXIF orientation data extractor
  5. -- @author Valentin Schmidt
  6. -- @version 0.2
  7. --
  8. -- Usage:
  9. -- res = getOrientation(_movie.path&"test.jpg")
  10. -- put "Orientation:" && res
  11. --****************************************************************************
  12.  
  13. ----------------------------------------
  14. -- Extracts orientation from JPEG file
  15. -- @param {string} jpgFile - path to JPEG file
  16. -- @return {integer} - orientation as positive number 1..8, or negative error code
  17. ----------------------------------------
  18. on getOrientation (jpgFile)
  19.   ba = _fileGetBytes(jpgFile)
  20.   if ilk(ba)<>#bytearray then return -3
  21.   return getOrientationFromData(ba)
  22. end
  23.  
  24. ----------------------------------------
  25. -- Extracts orientation from JPEG data passed as byteArray
  26. -- @param {byteArray} ba - the JPEG data
  27. -- @return {integer} - orientation as positive number 1..8, or negative error code
  28. ----------------------------------------
  29. on getOrientationFromData (ba)
  30.   if _getUint16(ba, 0, FALSE) <> 65496 then return -2
  31.   len = ba.length
  32.   offset = 2
  33.   repeat while (offset < len)
  34.     if _getUint16(ba, offset+2, FALSE) <= 8 then return -1
  35.     marker = _getUint16(ba, offset, FALSE)
  36.     offset = offset + 2
  37.     if (marker = 65505) then
  38.       offset = offset + 2
  39.       if _getUint32(ba, offset, FALSE) <> 1165519206 then return -1
  40.       offset = offset + 6
  41.       little = _getUint16(ba, offset, FALSE) = 18761
  42.       offset = offset + _getUint16(ba, offset + 4, little)
  43.       tags = _getUint16(ba, offset, little)
  44.       offset = offset + 2
  45.       repeat with i = 1 to tags
  46.         if _getUint16(ba, offset + (i * 12), little) = 274 then
  47.           return _getUint16(ba, offset + (i * 12) + 8, little)
  48.         end if
  49.       end repeat
  50.     else if bitAnd(marker, 65280) <> 65280 then
  51.       exit repeat
  52.     else
  53.       offset = offset + _getUint16(ba, offset, FALSE)
  54.     end if
  55.   end repeat
  56.   return -1
  57. end
  58.  
  59. ----------------------------------------
  60. -- Reads whole file, returns byteArray
  61. -- @param {string} fn
  62. -- @return {bytearray|FALSE}
  63. -- @private
  64. ----------------------------------------
  65. on _fileGetBytes (fn)
  66.   fp = xtra("fileIO").new()
  67.   fp.openFile(fn, 1)
  68.   if fp.status()<>0 then return FALSE
  69.   data = fp.readByteArray(fp.getLength())
  70.   fp.closeFile()
  71.   return data
  72. end
  73.  
  74. ----------------------------------------
  75. -- @private
  76. ----------------------------------------
  77. on _getUint16 (ba, pos, littleEndian)
  78.   if littleEndian then
  79.     return ba[pos+1] + 256*ba[pos+2]
  80.   else
  81.     return 256*ba[pos+1] + ba[pos+2]
  82.   end if
  83. end
  84.  
  85. ----------------------------------------
  86. -- Returns float, to overcome Director's signed int limit (the maxInteger)
  87. -- @private
  88. ----------------------------------------
  89. on _getUint32 (ba, pos, littleEndian)
  90.   if littleEndian then
  91.     return ba[pos+1] + 256*ba[pos+2] + 65536*ba[pos+3] + 16777216.*ba[pos+4]
  92.   else
  93.     return 16777216.*ba[pos+1] + 65536*ba[pos+2] + 256*ba[pos+3] + ba[pos+4]
  94.   end if
  95. end
  96.  
[raw code]