public bool Open(Stream fs) { try { var intSizeArr = new byte[4]; var shortSizeArr = new byte[2]; short shortSize; int intSize; long length; //Read JPG SOF (FF,D8) length = fs.Read(shortSizeArr, 0, 2); if (length != 2 || shortSizeArr[0] != 0xFF || shortSizeArr[1] != 0xD8) { errorMessage = "File has no 0xFFD8 on start!"; return false; } //READ First SOF 0:APP0:Jfif:0xFFE0 / 1:APP1:Exif:0xFFE1 length = fs.Read(shortSizeArr, 0, 2); if (shortSizeArr[0] == 0xFF && shortSizeArr[1] == 0xE0) { //If SOF0 found then skip it length = fs.Read(shortSizeArr, 0, 2); shortSize = ByteArrToShortBE(shortSizeArr); fs.Seek(shortSize - 2, SeekOrigin.Current); length = fs.Read(shortSizeArr, 0, 2); //Read next SOF# } if (shortSizeArr[0] != 0xFF || shortSizeArr[1] != 0xE1) //suppose to be next { errorMessage = "No Exif information (No APP1)"; return false; } //Skip over APP1 length = fs.Read(shortSizeArr, 0, 2); shortSize = ByteArrToShortBE(shortSizeArr); fs.Seek(shortSize - 2, SeekOrigin.Current); //Read next SOF 2:APP2:MPE:0xFFE2 length = fs.Read(shortSizeArr, 0, 2); if (length != 2 || shortSizeArr[0] != 0xFF || shortSizeArr[1] != 0xE2) { errorMessage = "File has no 0xFFE2 on start!"; return false; } fs.Seek(2, SeekOrigin.Current); //Skip over APP2 length field //Read MP Magic length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No MP Magic (MPF.)!"; return false; } if (!IsMPFMagic(intSizeArr)) { errorMessage = "Wrong MP Magic (MPF.)!"; return false; } var fromSOO = 0; //READ THE MP Header Endianess length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No APP2 Endianess!"; return false; } fromSOO += 4; var endianess = 0; if (intSizeArr[0] == 0x49 && intSizeArr[1] == 0x49 && intSizeArr[2] == 0x2A && intSizeArr[3] == 0x00) endianess = 1; // LE else if (intSizeArr[0] == 0x4D && intSizeArr[1] == 0x4D && intSizeArr[2] == 0x00 && intSizeArr[3] == 0x2A) endianess = 2; // BE if (endianess == 0) { errorMessage = "Wrong APP2 Endianess!"; return false; } //Read First IFD Offset length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No First IFD Offset!"; return false; } fromSOO += 4; intSize = (endianess == 1 ? BitConverter.ToInt32(intSizeArr, 0) : ByteArrToIntBE(intSizeArr)); if (intSize - fromSOO > 0) //Goto Offset fs.Seek(intSize - fromSOO, SeekOrigin.Current); // Skip MP Entry: Count[2], Version[12], No[12], No*16[12], Attr[4], Size[4] fs.Seek(46, SeekOrigin.Current); // Read 1st Image Size length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No Image Size!"; return false; } intSize = (endianess == 1 ? BitConverter.ToInt32(intSizeArr, 0) : ByteArrToIntBE(intSizeArr)); fs.Seek(0, SeekOrigin.Begin); LeftImageBytes = new byte[intSize]; fs.Read(LeftImageBytes, 0, intSize); LeftImage = ByteArrayToImage(LeftImageBytes); // Go to the start of the next file (skip junk) //int space = 1; var found = false; while (!found) { if (fs.ReadByte() == 0xFF) { if (fs.ReadByte() == 0xD8) { found = true; } } } fs.Seek(-2, SeekOrigin.Current); intSize = 0; RightImageBytes = new byte[fs.Length - intSize - 1]; fs.Read(RightImageBytes, 0, (int)(fs.Length - intSize - 1)); RightImage = ByteArrayToImage(RightImageBytes); fs.Close(); fs = null; var propItems = LeftImage.PropertyItems; var nintendo = false; foreach (var propItem in propItems) { if (propItem.Id == 0x010F) // Manufacturer nintendo = Encoding.UTF8.GetString(propItem.Value).Equals("Nintendo\0"); else if ((propItem.Id == 0x927C) && nintendo) // MakerNote { var memStream = new MemoryStream(propItem.Value); var ifdCount = (ushort)(memStream.ReadByte() << 8); ifdCount += (byte)memStream.ReadByte(); _ifds = new IFD[ifdCount]; for (var i=0;i<_ifds.Length;i++) _ifds[i] = MarshalUtil.ReadStructBE<IFD>(memStream) ; //read the zero //ifdCount = (ushort)(memStream.ReadByte() << 8); //ifdCount += (byte)memStream.ReadByte(); //jump over the first ifd memStream.Seek(4, SeekOrigin.Current); _firstIFDData = new byte[_ifds[0].CountValue]; memStream.Read(_firstIFDData, 0, _firstIFDData.Length); _nintendoNote = MarshalUtil.ReadStruct<NintendoNote>(memStream); memStream.Close(); break; } } var px = _nintendoNote.Parallax == 0 ? -10 : _nintendoNote.Parallax; //make images for animation LeftLaxxedImage = new Bitmap(LeftImage.Width + (int)px, LeftImage.Height); RightLaxxedImage = new Bitmap(RightImage.Width + (int)px, RightImage.Height); var g = Graphics.FromImage(LeftLaxxedImage); g.DrawImage(LeftImage, new Rectangle(0, 0, RightImage.Width + (int)px, RightImage.Height), new Rectangle(0, 0, LeftImage.Width + (int)px, LeftImage.Height), GraphicsUnit.Pixel); g.Dispose(); g = Graphics.FromImage(RightLaxxedImage); g.DrawImage(RightImage, new Rectangle(0, 0, RightImage.Width + (int)px, RightImage.Height), new Rectangle(-(int)px, 0, RightImage.Width + (int)px, RightImage.Height), GraphicsUnit.Pixel); g.Dispose(); //make anaglyph AnaglyphImage = Anaglyph.MakeAnaglyph(LeftImage, RightImage, (new Anaglyph()).HalfColorAnaglyph, (int)px); return true; } catch (Exception ex) { errorMessage = "Error in Opening file:" + Environment.NewLine + ex.Message; return false; } finally { if (fs != null) fs.Close(); } }
public bool Open(Stream fs) { try { var intSizeArr = new byte[4]; var shortSizeArr = new byte[2]; short shortSize; int intSize; long length; //Read JPG SOF (FF,D8) length = fs.Read(shortSizeArr, 0, 2); if (length != 2 || shortSizeArr[0] != 0xFF || shortSizeArr[1] != 0xD8) { errorMessage = "File has no 0xFFD8 on start!"; return(false); } //READ First SOF 0:APP0:Jfif:0xFFE0 / 1:APP1:Exif:0xFFE1 length = fs.Read(shortSizeArr, 0, 2); if (shortSizeArr[0] == 0xFF && shortSizeArr[1] == 0xE0) { //If SOF0 found then skip it length = fs.Read(shortSizeArr, 0, 2); shortSize = ByteArrToShortBE(shortSizeArr); fs.Seek(shortSize - 2, SeekOrigin.Current); length = fs.Read(shortSizeArr, 0, 2); //Read next SOF# } if (shortSizeArr[0] != 0xFF || shortSizeArr[1] != 0xE1) //suppose to be next { errorMessage = "No Exif information (No APP1)"; return(false); } //Skip over APP1 length = fs.Read(shortSizeArr, 0, 2); shortSize = ByteArrToShortBE(shortSizeArr); fs.Seek(shortSize - 2, SeekOrigin.Current); //Read next SOF 2:APP2:MPE:0xFFE2 length = fs.Read(shortSizeArr, 0, 2); if (length != 2 || shortSizeArr[0] != 0xFF || shortSizeArr[1] != 0xE2) { errorMessage = "File has no 0xFFE2 on start!"; return(false); } fs.Seek(2, SeekOrigin.Current); //Skip over APP2 length field //Read MP Magic length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No MP Magic (MPF.)!"; return(false); } if (!IsMPFMagic(intSizeArr)) { errorMessage = "Wrong MP Magic (MPF.)!"; return(false); } var fromSOO = 0; //READ THE MP Header Endianess length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No APP2 Endianess!"; return(false); } fromSOO += 4; var endianess = 0; if (intSizeArr[0] == 0x49 && intSizeArr[1] == 0x49 && intSizeArr[2] == 0x2A && intSizeArr[3] == 0x00) { endianess = 1; // LE } else if (intSizeArr[0] == 0x4D && intSizeArr[1] == 0x4D && intSizeArr[2] == 0x00 && intSizeArr[3] == 0x2A) { endianess = 2; // BE } if (endianess == 0) { errorMessage = "Wrong APP2 Endianess!"; return(false); } //Read First IFD Offset length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No First IFD Offset!"; return(false); } fromSOO += 4; intSize = (endianess == 1 ? BitConverter.ToInt32(intSizeArr, 0) : ByteArrToIntBE(intSizeArr)); if (intSize - fromSOO > 0) //Goto Offset { fs.Seek(intSize - fromSOO, SeekOrigin.Current); } // Skip MP Entry: Count[2], Version[12], No[12], No*16[12], Attr[4], Size[4] fs.Seek(46, SeekOrigin.Current); // Read 1st Image Size length = fs.Read(intSizeArr, 0, 4); if (length != 4) { errorMessage = "No Image Size!"; return(false); } intSize = (endianess == 1 ? BitConverter.ToInt32(intSizeArr, 0) : ByteArrToIntBE(intSizeArr)); fs.Seek(0, SeekOrigin.Begin); LeftImageBytes = new byte[intSize]; fs.Read(LeftImageBytes, 0, intSize); LeftImage = ByteArrayToImage(LeftImageBytes); // Go to the start of the next file (skip junk) //int space = 1; var found = false; while (!found) { if (fs.ReadByte() == 0xFF) { if (fs.ReadByte() == 0xD8) { found = true; } } } fs.Seek(-2, SeekOrigin.Current); intSize = 0; RightImageBytes = new byte[fs.Length - intSize - 1]; fs.Read(RightImageBytes, 0, (int)(fs.Length - intSize - 1)); RightImage = ByteArrayToImage(RightImageBytes); fs.Close(); fs = null; var propItems = LeftImage.PropertyItems; var nintendo = false; foreach (var propItem in propItems) { if (propItem.Id == 0x010F) // Manufacturer { nintendo = Encoding.UTF8.GetString(propItem.Value).Equals("Nintendo\0"); } else if ((propItem.Id == 0x927C) && nintendo) // MakerNote { var memStream = new MemoryStream(propItem.Value); var ifdCount = (ushort)(memStream.ReadByte() << 8); ifdCount += (byte)memStream.ReadByte(); _ifds = new IFD[ifdCount]; for (var i = 0; i < _ifds.Length; i++) { _ifds[i] = MarshalUtil.ReadStructBE <IFD>(memStream); } //read the zero //ifdCount = (ushort)(memStream.ReadByte() << 8); //ifdCount += (byte)memStream.ReadByte(); //jump over the first ifd memStream.Seek(4, SeekOrigin.Current); _firstIFDData = new byte[_ifds[0].CountValue]; memStream.Read(_firstIFDData, 0, _firstIFDData.Length); _nintendoNote = MarshalUtil.ReadStruct <NintendoNote>(memStream); memStream.Close(); break; } } var px = _nintendoNote.Parallax == 0 ? -10 : _nintendoNote.Parallax; //make images for animation LeftLaxxedImage = new Bitmap(LeftImage.Width + (int)px, LeftImage.Height); RightLaxxedImage = new Bitmap(RightImage.Width + (int)px, RightImage.Height); var g = Graphics.FromImage(LeftLaxxedImage); g.DrawImage(LeftImage, new Rectangle(0, 0, RightImage.Width + (int)px, RightImage.Height), new Rectangle(0, 0, LeftImage.Width + (int)px, LeftImage.Height), GraphicsUnit.Pixel); g.Dispose(); g = Graphics.FromImage(RightLaxxedImage); g.DrawImage(RightImage, new Rectangle(0, 0, RightImage.Width + (int)px, RightImage.Height), new Rectangle(-(int)px, 0, RightImage.Width + (int)px, RightImage.Height), GraphicsUnit.Pixel); g.Dispose(); //make anaglyph AnaglyphImage = Anaglyph.MakeAnaglyph(LeftImage, RightImage, (new Anaglyph()).HalfColorAnaglyph, (int)px); return(true); } catch (Exception ex) { errorMessage = "Error in Opening file:" + Environment.NewLine + ex.Message; return(false); } finally { if (fs != null) { fs.Close(); } } }