using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; using System.IO; // Quick and dirty code... Sorry... namespace QuickJPGfromCR2 { public partial class FormPrincipal : Form { public FormPrincipal() { InitializeComponent(); labelMessage.Text = ""; labelJpgFolder.Text = pleaseChooseFolderMessage; labelCr2Folder.Text = pleaseChooseFolderMessage; progressBar.Visible = false; EnableActions(); } string[] m_cr2Files; int m_nbFiles = 0; static byte[] buffer = new byte[BUF_SIZE]; const int BUF_SIZE = 512 * 1024; readonly string pleaseChooseFolderMessage = "Please choose a folder."; void EnableActions() { buttonJpgFolder.Enabled = radioButtonChooseFolder.Checked; labelJpgFolder.Visible = radioButtonChooseFolder.Checked; buttonExtractJPG.Enabled = m_nbFiles > 0 && (!radioButtonChooseFolder.Checked || labelJpgFolder.Text != pleaseChooseFolderMessage); } private void buttonCr2Folder_Click(object sender, EventArgs e) { FolderBrowserDialog d = new FolderBrowserDialog(); d.RootFolder = Environment.SpecialFolder.Desktop; d.ShowNewFolderButton = false; d.Description = "Choose a folder containing raw (.CR2) files:"; if (DialogResult.OK == d.ShowDialog()) { labelCr2Folder.Text = d.SelectedPath; try { m_cr2Files = Directory.GetFiles(labelCr2Folder.Text, "*.CR2"); m_nbFiles = m_cr2Files.Length; for (int i = 0; i != m_cr2Files.Length; ++i) { if (!m_cr2Files[i].ToUpper().EndsWith(".CR2")) // .CR2withmore { m_cr2Files[i] = null; --m_nbFiles; } } if (m_nbFiles == 0) labelMessage.Text = "No raw (.CR2) files in folder."; else { labelMessage.Text = String.Format("{0} raw (.CR2) file{1} found.", m_nbFiles, (m_nbFiles > 1) ? "s" : ""); } } catch (DirectoryNotFoundException) { labelMessage.Text = "Invalid folder name."; m_nbFiles = 0; } progressBar.Maximum = m_nbFiles; progressBar.Value = 0; EnableActions(); } } private void radioButtonFolder_CheckedChanged(object sender, EventArgs e) { EnableActions(); } private void buttonJpgFolder_Click(object sender, EventArgs e) { FolderBrowserDialog d = new FolderBrowserDialog(); d.ShowNewFolderButton = false; d.RootFolder = Environment.SpecialFolder.Desktop; if (labelJpgFolder.Text != pleaseChooseFolderMessage) d.SelectedPath = labelJpgFolder.Text; else if (labelCr2Folder.Text != pleaseChooseFolderMessage) d.SelectedPath = labelCr2Folder.Text; if (DialogResult.OK == d.ShowDialog()) { labelJpgFolder.Text = d.SelectedPath; EnableActions(); } } private void buttonExtractJPG_Click(object sender, EventArgs e) { string outFolder; if (radioButtonSameFolder.Checked) { outFolder = labelCr2Folder.Text; // Not really used in this case... if (outFolder.EndsWith("\\")) outFolder = outFolder.Substring(0, outFolder.Length - 1); } else if (radioButtonJpgSubfolder.Checked) { outFolder = labelCr2Folder.Text; if (outFolder.EndsWith("\\")) outFolder += "JPG"; else outFolder += "\\JPG"; if (!Directory.Exists(outFolder)) { try { Directory.CreateDirectory(outFolder); } catch { labelMessage.Text = "Unabled to access or create JPG subfolder."; return; } } } else { outFolder = labelJpgFolder.Text; if (outFolder.EndsWith("\\")) outFolder = outFolder.Substring(0, outFolder.Length - 1); } progressBar.Visible = true; progressBar.Value = 0; labelMessage.Text = "Processing..."; int nbExtracted = 0; int nbRotated = 0; foreach (string fileName in m_cr2Files) { if (fileName != null) { FileStream fi = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, BUF_SIZE, FileOptions.None); // Start address is at offset 0x62, file size at 0x7A, orientation at 0x6E fi.Seek(0x62, SeekOrigin.Begin); BinaryReader br = new BinaryReader(fi); UInt32 jpgStartPosition = br.ReadUInt32(); // 62 br.ReadUInt32(); // 66 br.ReadUInt32(); // 6A UInt32 orientation= br.ReadUInt32() & 0x000000FF; // 6E br.ReadUInt32(); // 72 br.ReadUInt32(); // 76 Int32 fileSize = br.ReadInt32(); // 7A fi.Seek(jpgStartPosition, SeekOrigin.Begin); if (fi.ReadByte() != 0xFF || fi.ReadByte() != 0xD8) { MessageBox.Show(String.Format("{0}\nEmbedded JPG not recognized. File skipped.", fileName), "Quick JPG from CR2", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { string baseName = fileName.Substring(0, fileName.Length - 4); if (!radioButtonSameFolder.Checked) { int endOfPath = baseName.LastIndexOf('\\'); baseName = outFolder + baseName.Substring(endOfPath); } string jpgName = baseName + ".jpg"; if ( ! checkBoxAutoOverwrite.Checked && File.Exists(jpgName)) { int version = 1; do { jpgName = String.Format("{0}_{1}.jpg", baseName, version); ++version; } while (File.Exists(jpgName)); } if (checkBoxRotate.Checked && m_codecJpeg != null && (orientation == 8 || orientation == 6)) { Bitmap bitmap = new Bitmap(new PartialStream(fi, jpgStartPosition, fileSize)); if (orientation == 8) bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone); else bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone); EncoderParameters ep = new EncoderParameters(1); ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L); bitmap.Save(jpgName, m_codecJpeg, ep); ++nbRotated; } else { FileStream fo = File.Create(jpgName, BUF_SIZE, FileOptions.None); fi.Seek(jpgStartPosition, SeekOrigin.Begin); do { int nRead = fi.Read(buffer, 0, Math.Min(fileSize, BUF_SIZE)); if (nRead == 0) fileSize = 0; else { fo.Write(buffer, 0, nRead); fileSize -= nRead; } } while (fileSize > 0); fo.Close(); } } fi.Close(); progressBar.Value = ++nbExtracted; } } if (nbRotated == 0) labelMessage.Text = "Done."; else labelMessage.Text = String.Format("Done ({0} rotated).", nbRotated); progressBar.Visible = false; } static ImageCodecInfo m_codecJpeg = GetJpegCodec(); private static ImageCodecInfo GetJpegCodec() { foreach (ImageCodecInfo c in ImageCodecInfo.GetImageEncoders()) { if (c.CodecName.ToLower().Contains("jpeg") || c.FilenameExtension.ToLower().Contains("*.jpg") || c.FormatDescription.ToLower().Contains("jpeg") || c.MimeType.ToLower().Contains("image/jpeg")) return c; } return null; } } class PartialStream : Stream // Fun solution and experiment... probably not the best idea here { internal PartialStream(FileStream p_f, uint p_start, int p_length) { m_f = p_f; m_start= p_start; m_length = p_length; m_f.Seek(p_start, SeekOrigin.Begin); } FileStream m_f; uint m_start; int m_length; public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return m_f.BeginRead(buffer, offset, count, callback, state); } public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return m_f.BeginWrite(buffer, offset, count, callback, state); } public override bool CanRead { get { return m_f.CanRead; } } public override bool CanSeek { get { return m_f.CanSeek; } } public override bool CanTimeout { get { return m_f.CanTimeout; } } public override bool CanWrite { get { return m_f.CanWrite; } } public override void Close() { m_f.Close(); } public override System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType) { return m_f.CreateObjRef(requestedType); } protected override void Dispose(bool disposing) { //m_f.Dispose(disposing); // Can't... base.Dispose(disposing); } public override int EndRead(IAsyncResult asyncResult) { return m_f.EndRead(asyncResult); } public override void EndWrite(IAsyncResult asyncResult) { m_f.EndWrite(asyncResult); } public override bool Equals(object obj) { return m_f.Equals(obj); } public override void Flush() { m_f.Flush(); } public override int GetHashCode() { return m_f.GetHashCode(); } public override object InitializeLifetimeService() { return m_f.InitializeLifetimeService(); } public override long Length { get { return m_length; } } public override long Position { get { return m_f.Position - m_start; } set { m_f.Position = value + m_start; } } public override int Read(byte[] buffer, int offset, int count) { long maxRead = Length - Position; return m_f.Read(buffer, offset, (count <= maxRead) ? count : (int)maxRead); } public override int ReadByte() { if (Position < Length) return m_f.ReadByte(); else return 0; } public override int ReadTimeout { get { return m_f.ReadTimeout; } set { m_f.ReadTimeout = value; } } public override void SetLength(long value) { m_f.SetLength(value); } public override string ToString() { return m_f.ToString(); } public override void Write(byte[] buffer, int offset, int count) { m_f.Write(buffer, offset, count); } public override void WriteByte(byte value) { m_f.WriteByte(value); } public override int WriteTimeout { get { return m_f.WriteTimeout; } set { m_f.WriteTimeout = value; } } public override long Seek(long offset, SeekOrigin origin) { return m_f.Seek(offset+m_start, origin); } } }