2017-03-13 25 views
1

用這個項目搔癢的樣子 - 或者說兩個。一個是試圖使用Xcode編寫macOS應用程序,另一個是處理3D照片(或者如果您完全正確,則使用StereoPhotos)。打開MPO文件並提取嵌入的圖像

我在LiveCode中嘗試了這一點,但它很慢且很麻煩。我得到了我喜歡的東西,但是你很快就撞上了高性能牆。所以我決定在Xcode中重新啓動。我想要做的一件事是從富士3D相機導入MPO文件,提取左右圖像,並將其顯示在我的應用程序中。在LiveCode中這很容易(可能太簡單了) - 您將MPO文件導入爲文本字符串,使用JPEG標記將其分割爲數組,然後將該數據設置爲圖像對象。結果是兩個JPEG文件。

我一直在Swift中嘗試這個,並且失敗的很厲害。在將它添加到我的應用程序之前,到目前爲止在Playground中嘗試創意。我一直採用與我在LiveCode中相同的邏輯 - 加載數據,用標記分割文件,保存數據。

import Cocoa 
import Foundation 

// Files and destinations 
let MPOString = "/path/to/DSCF0523.MPO" 
let myLeft = URL(string:"file:///path/to/left.jpg") 
let myRight = URL(string:"file:///path/to/right.jpg") 

var leftImage:NSImage 
var rightImage:NSImage 

//JPEG Marker FFD8FFE1 
let myJpegMarker = "\u{FF}\u{D8}\u{FF}\u{E1}" 

do { 
    myMPOData = try String(contentsOfFile: MPOString , encoding:String.Encoding.isoLatin1) as NSString 
} 
catch { 
    print("Error getting MPO - \(myMPOData)\n\(MPOString)") 
} 

/* 
At this point, I realise that while the data has been split, 
the markers are removed, so I add them back. 
This is wrong (but worked in LiveCode) 
*/ 
let imageArray = myMPOData.components(separatedBy: myJpegMarker) 

var myLeftImage = myJpegMarker+imageArray[1] 
var myRightImage = myJpegMarker+imageArray[2] 

do { 
    try myLeftImage.write(to: myLeft! , atomically: false, encoding: String.Encoding.utf8) 
} 
catch { 
    print("Error writing file: " + error.localizedDescription) 
} 

print ("Saving image \(myRight)") 
do { 
    try myRightImage.write(to: myRight! , atomically: false, encoding: String.Encoding.utf8) 
} 
catch { 
    print("Error writing file: " + error.localizedDescription) 
} 

上面的代碼做了接近,但不夠緊密。我的意思是說,它將數據分開,並丟棄兩個文件。但是這些文件是不正確的。十六進制轉儲告訴我,JPEG標記不正確(我在文件的開頭尋找FFD8FFE1,但那不是 - 有8個額外的字符,我期望是編碼的結果)。此外,文件大小也太有點 - 6.5Mb而不是預期的4,這告訴我有些事情是不正確的。

我花了相當長的時間試圖找到一個解決方案,但我發現自己圍繞着同樣的谷歌搜索結果出現在圈子裏。

東西告訴我應該可以將圖像加載到對象中,並通過引用object [0]和object [1]來獲取它們。無論如何,無論解決方案如何,我預計它可能比我預期的要簡單。

我已經在DropBox上放置了一個示例MPO文件供大家參考,如果有人覺得他們可以提供幫助。 https://dl.dropboxusercontent.com/u/613685/DSCF0523.MPO.zip

回答

0

我認爲問題在於使用(NS)字符串而不是(NS)數據作爲您的方法的基礎。

雖然可能不是最巧妙的解決方案(我的心是在Objective-C模式,所以我非常多懷疑下面的雨燕可能是兩者的令人不安的組合),但是這應該提取嵌入圖片:

import Foundation 

let jpegMarker:Data = Data(bytes: UnsafePointer<UInt8>([0xFF, 0xD8, 0xFF, 0xE1] as [uint8]), count: 4) 

let baseURL = "file:///path/to/images/" 
let mpoURL = URL(string: baseURL + "DSCF0523.MPO") 
var mpoData:Data 

do { 
    try mpoData = Data.init(contentsOf: mpoURL!) 
    var markerLocations:[Int] = [] 
    var markerOffset:Range? = mpoData.range(of: jpegMarker, options:[], in:0 ..< mpoData.count) 

    while (markerOffset != nil) { 

     // We've found a marker - add it to our array 
     markerLocations.append(markerOffset!.lowerBound) 

     // Update our current offset before we iterate 
     markerOffset = mpoData.range(of: jpegMarker as Data, options:[], in:markerOffset!.upperBound ..< mpoData.count) 
    } 


    // Did we find any markers? 
    if (markerLocations.count != 0) { 

     // Time to extract the data betwen the markers 
     for (index, currentMarkerOffset) in markerLocations.enumerated() { 

      let endDataOffset = index == markerLocations.count - 1 ? mpoData.count : markerLocations[index + 1] 
      let imageBytes:Data = mpoData.subdata(in:currentMarkerOffset ..< endDataOffset) 

      // Write the image data to disk 
      do { 
       let outputPath = baseURL + "Image-" + String(index) + ".jpeg" 
       try imageBytes.write(to: URL(string: outputPath)!) 
      } 
      catch { 
       print("Unable to write image file - " + error.localizedDescription) 
      } 
     } 

    } else { 
     print("JPEG marker not found in source MPO file.") 
    } 

} catch { 
    print("Unable to open source MPO file - " + error.localizedDescription) 
} 

我在做的是最初在一個while循環中獲取文件中的所有標記(因爲它可能有兩個以上的嵌入圖像),然後迭代並逐一提取它們。

在此迭代過程中,我們必須處理最終標記的情況,因此需要使用相當醜陋的三元條件運算符。

順便提一下,這個使用Swift 3的Data(而不是2.x風格的NSData)等。

+1

謝謝!我已經在Playground和我正在開發的應用程序中嘗試過這一點,它正在做我希望的事情。 後來我發佈了我的問題,我應該使用數據而不是字符串 - 我正在閱讀範圍。 –