Monday, July 25, 2011

Split .MPO file into left and right .JPG files

This morning, I got csharp code working that splits an MPO file from a Fujifilm FinePix Real3D camera into left and right components. Here is the code that does it.

using System;
using System.IO;
using System.Collections;

/// <summary>
/// Breaks an MPO file into two JPG files having names _L.jpg and _R.jpg.
/// Throws error if source file does not have .mpo extension.
/// Works by searching for 4 bytes: ff d8 ff e1 which is the start of both files.
/// Throws error if file does not start with ff d8 ff e1.
/// Throws error if other than one additional ff d8 ff e1 is found.
/// </summary>
/// <param name="sFullFileName">Full path to the .MPO file being split</param>
/// <param name="bOverwrite">If true, it will overwrite any existing left or right files. If false, it throws and error of the target files already exist</param>
public static void SplitMpoFile(string sFullPath, bool bOverwrite) {
    string sExt = sFullPath.Substring(sFullPath.Length - 4);
    if (sExt.ToUpper() != ".MPO") {
        throw new Exception(sFullPath + " does not have .MPO extension.");
    }
    string sFileNameBase = sFullPath.Substring(0, sFullPath.Length - 4);
    string sFileNameLeft = sFileNameBase + "_L.jpg";
    string sFileNameRght = sFileNameBase + "_R.jpg";
    if (File.Exists(sFileNameLeft)) {
        if (bOverwrite) {
            File.Delete(sFileNameLeft);
        }else{
            throw new Exception(sFileNameLeft + " already exists.");
        }
    }
    if (File.Exists(sFileNameRght)) {
        if (bOverwrite) {
            File.Delete(sFileNameRght);
        }else{
            throw new Exception(sFileNameRght + " already exists.");
        }
    }
      
    FileStream fs = new FileStream(sFullPath, FileMode.Open);
    long lFileLength = fs.Length;
    byte[] bytes = new byte[lFileLength];
    BinaryReader br = new BinaryReader(fs);
    br.Read(bytes, 0, (int)lFileLength);
    br.Close();
    fs.Close();

    // Verify that file starts with ff d8 ff e1
    if (bytes[0] != 255 || bytes[1] != 216 || bytes [2] != 255 || bytes[3] != 225) {
        throw new Exception(sFullPath + " does not start with correct code.");
    }
    // Make an array list of all the places in the file that start with ff d8 ff e1
    ArrayList alBreakPoints = new ArrayList(8);
    for (int i = 1; i < lFileLength - 4; i++) {
        if (bytes[i] == 255 && bytes[i + 1] == 216 && bytes[i + 2] == 255 && bytes[i + 3] == 225) {
            alBreakPoints.Add(i);
        }
    }
    // At this point, there should be exactly 1 element in the array list.
    if (alBreakPoints.Count != 1) {
        throw new Exception(alBreakPoints.Count + " breakpoints found in " + sFullPath);
    }
    int iBreakPoint = (int)alBreakPoints[0];

    // OK - everything looks good here. Output the two parts of the file.
    fs = new FileStream(sFileNameLeft, FileMode.CreateNew);
    BinaryWriter bw = new BinaryWriter(fs);
    bw.Write(bytes, 0, iBreakPoint);
    bw.Close();
    fs.Close();
    fs = new FileStream(sFileNameRght, FileMode.CreateNew);
    bw = new BinaryWriter(fs);
    bw.Write(bytes, iBreakPoint, (int)lFileLength - iBreakPoint);
    bw.Close();
    fs.Close();


}

No comments:

Post a Comment