public Vr180Jpeg(Bitmap left, Bitmap right, ExifReadWrite exifSegment, long jpegQuality) { GetLeftEye = left; GetRightEye = right; ExifSegment = exifSegment; JpegQuality = jpegQuality; }
private static void ProcessFile(string inputFileName, string outputFileName, long jpegQuality = 100) { LinkedList <Tuple <string, byte[]> > jpegSegments; JpegFile jpegFile = new JpegFile(); Dictionary <string, string> panoDict; byte[] extendedXMPURI = Encoding.UTF8.GetBytes("http://ns.adobe.com/xmp/extension/"); byte[] zeroByte = { 0x0 }; byte[] extendedXMPSignature = null; string extendXMP = ""; // string inputJpeg = args[0]; // string outputJpeg = args[1]; ExifReadWrite exif = new ExifReadWrite(); using (var stream = File.OpenRead(inputFileName)) jpegSegments = jpegFile.Parse(stream); bool xmpFound = false; bool extendedXMPFound = false; foreach (var segment in jpegSegments) { //Console.WriteLine(segment.Item1); if (segment.Item1 == "EXIF") { exif.ReadExifAPP1(segment.Item2); } if (xmpFound != true && segment.Item1 == "APP1") { string start = Encoding.UTF8.GetString(segment.Item2, 0, 28); if (start == "http://ns.adobe.com/xap/1.0/") { // XMP, extract the GPano if its there. panoDict = jpegFile.ExtractGPano(Encoding.UTF8.GetString(segment.Item2, 29, segment.Item2.Length - 29)); string xmpMD5; if (panoDict.TryGetValue("xmpNote:HasExtendedXMP", out xmpMD5)) { extendedXMPSignature = extendedXMPURI.Concat(zeroByte).Concat(Encoding.UTF8.GetBytes(xmpMD5)).ToArray(); extendedXMPFound = true; } } } if (extendedXMPFound == true && segment.Item1 == "APP1" && jpegFile.segmentCompare(extendedXMPSignature, segment.Item2)) { extendXMP += jpegFile.ProcessExtendedXMPSegemnt(segment.Item2, extendXMP.Length); } } var md5 = System.Security.Cryptography.MD5.Create(); var md5hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(extendXMP)); var sb = new StringBuilder(); for (int i = 0; i < md5hash.Length; i++) { sb.Append(md5hash[i].ToString("x2")); } if (extendXMP.Length > 0) { var newJpeg = jpegFile.ProcessExtendedXMPXML(extendXMP); if (newJpeg != null) { jpegFile.WriteCombineImage(inputFileName, outputFileName, newJpeg, exif, jpegQuality); } } }
public Vr180Jpeg SplitImage(string orginalJpeg, string format, long newJpegQuailty) { Bitmap firstHalf, secondHalf; Bitmap originalImage = new Bitmap(Image.FromFile(orginalJpeg)); Rectangle rect; switch (format) { case "lr": rect = new Rectangle(0, 0, originalImage.Width / 2, originalImage.Height); firstHalf = originalImage.Clone(rect, originalImage.PixelFormat); rect = new Rectangle(originalImage.Width / 2, 0, originalImage.Width / 2, originalImage.Height); secondHalf = originalImage.Clone(rect, originalImage.PixelFormat); break; case "rl": rect = new Rectangle(originalImage.Width / 2, 0, originalImage.Width / 2, originalImage.Height); firstHalf = originalImage.Clone(rect, originalImage.PixelFormat); rect = new Rectangle(0, 0, originalImage.Width / 2, originalImage.Height); secondHalf = originalImage.Clone(rect, originalImage.PixelFormat); break; case "tb": rect = new Rectangle(0, 0, originalImage.Width, originalImage.Height / 2); firstHalf = originalImage.Clone(rect, originalImage.PixelFormat); rect = new Rectangle(0, originalImage.Height / 2, originalImage.Width, originalImage.Height / 2); secondHalf = originalImage.Clone(rect, originalImage.PixelFormat); break; case "bt": rect = new Rectangle(0, originalImage.Height / 2, originalImage.Width, originalImage.Height / 2); firstHalf = originalImage.Clone(rect, originalImage.PixelFormat); rect = new Rectangle(0, 0, originalImage.Width, originalImage.Height / 2); secondHalf = originalImage.Clone(rect, originalImage.PixelFormat); break; default: firstHalf = null; secondHalf = null; break; } originalImage.Dispose(); var exiflib = new ExifReadWrite(); using (FileStream fs = new FileStream(orginalJpeg, FileMode.Open, FileAccess.Read)) { var segments = Parse(fs); foreach (var segment in segments) { if (segment.Item1 == "EXIF") { exiflib.ReadExifAPP1(segment.Item2); } } } return(new Vr180Jpeg(firstHalf, secondHalf, exiflib, newJpegQuailty)); }
public string WriteCombineImage(string inputJpeg, string outputJpeg, byte[] newJpeg, ExifReadWrite exif, long jpegQuality) { Image img1 = Image.FromFile(inputJpeg); Image img2 = Image.FromStream(new MemoryStream(newJpeg)); Bitmap newBitmap; Graphics canvas; int height, width; int EXIF_HEIGHT_ID = 0x0100; int EXIF_WIDTH_ID = 0x0101; // Draw both images to one bitmap if (img1.Width > img1.Height) { // top bottom height = img1.Height + img2.Height; width = Math.Max(img1.Width, img2.Width); newBitmap = new Bitmap(width, height); canvas = Graphics.FromImage(newBitmap); canvas.Clear(Color.Black); canvas.DrawImage(img1, new Point(0, 0)); canvas.DrawImage(img2, new Point(0, img1.Height)); } else { width = img1.Width + img2.Width; height = Math.Max(img1.Height, img2.Height); newBitmap = new Bitmap(width, height); canvas = Graphics.FromImage(newBitmap); canvas.Clear(Color.Black); canvas.DrawImage(img1, new Point(0, 0)); canvas.DrawImage(img2, new Point(img1.Width, 0)); } foreach (PropertyItem property in img1.PropertyItems) { if (property.Id == EXIF_HEIGHT_ID) { byte[] newHeight = BitConverter.GetBytes(height); property.Value = newHeight; } else if (property.Id == EXIF_WIDTH_ID) { byte[] newWidth = BitConverter.GetBytes(width); property.Value = newWidth; } newBitmap.SetPropertyItem(property); } // clear up the memory, we only need the bitmap from the combined image for here in. canvas.Dispose(); img1.Dispose(); img2.Dispose(); using (MemoryStream jpegms = new MemoryStream()) using (FileStream jpegOut = new FileStream(outputJpeg, FileMode.OpenOrCreate, FileAccess.Write)) { // write the combined image in a in-memory temporary jpeg as we need to manipulate the metadata before writing to disk. using (EncoderParameters encoderParameters = new EncoderParameters(1)) using (EncoderParameter encoderParameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, jpegQuality)) { ImageCodecInfo codecInfo = ImageCodecInfo.GetImageDecoders().First(codec => codec.FormatID == ImageFormat.Jpeg.Guid); encoderParameters.Param[0] = encoderParameter; newBitmap.Save(jpegms, codecInfo, encoderParameters); } height = newBitmap.Height; width = newBitmap.Width; newBitmap.Dispose(); jpegms.Flush(); jpegms.Position = 0; byte[] jpegTagBuffer = new byte[2]; byte[] jpegLengthBuffer = new byte[2]; byte[] networkLength = new byte[2]; jpegms.Read(jpegTagBuffer, 0, 2); jpegOut.Write(jpegTagBuffer, 0, 2); bool writeExifRead = false; while (writeExifRead == false) { jpegms.Read(jpegTagBuffer, 0, 2); if (jpegTagBuffer[0] == 0xFF && (jpegTagBuffer[1] == 0xE1 || jpegTagBuffer[1] == 0xE0)) { jpegms.Read(jpegLengthBuffer, 0, 2); if (BitConverter.IsLittleEndian) { networkLength[0] = jpegLengthBuffer[1]; networkLength[1] = jpegLengthBuffer[0]; } else { networkLength[0] = jpegLengthBuffer[0]; networkLength[1] = jpegLengthBuffer[1]; } ushort length = BitConverter.ToUInt16(networkLength, 0); byte[] segment = new byte[length - 2]; jpegms.Read(segment, 0, length - 2); // skip an exif if we are copying the originals if (segment[0] == 'E' && segment[1] == 'x' && segment[2] == 'i' && segment[3] == 'f' && segment[4] == 0x00 && exif.Properties.Count > 0) { Console.WriteLine("New Jpeg has an existing Exif, replacing."); continue; } // write it out jpegOut.Write(jpegTagBuffer, 0, 2); jpegOut.Write(jpegLengthBuffer, 0, 2); jpegOut.Write(segment, 0, length - 2); } else { writeExifRead = true; } } // add in an Exif if we've got properties... if (exif.Properties.Count > 0) { // replace height and width foreach (var prop in exif.Properties) { // Console.WriteLine(prop.Name); if (prop.Name == "PixelXDimension") { prop.Value = (uint)width; } if (prop.Name == "PixelYDimension") { prop.Value = (uint)height; } } byte[] exifBuffer = exif.WriteExifApp1(true); byte[] exifTagBuffer = { 0xFF, 0xE1 }; ushort exifLength = (ushort)(exifBuffer.Length + 2); networkLength = BitConverter.GetBytes(exifLength); if (BitConverter.IsLittleEndian) { Array.Reverse(networkLength); } jpegOut.Write(exifTagBuffer, 0, 2); jpegOut.Write(networkLength, 0, 2); jpegOut.Write(exifBuffer, 0, exifBuffer.Length); } // finish of writing the jpeg, starting with the last tag read. jpegOut.Write(jpegTagBuffer, 0, 2); jpegms.CopyTo(jpegOut); jpegms.Flush(); jpegOut.Flush(); } return("OK"); }