This is the code where I save the frames/images to the hard disk.
I rotate the images twice once in 180 degrees then once again in 90 degrees.
But the video show the woman walking from left to right but after the rotation I see it in the pictureBox using the trackBar scroll moving from right to left like a mirror.
This is how it looks like after the rotation:
She start to walk from right to left her face are looking to the left when in the original it should be from left to right.
This is how it looks when I rotate it to 180 degrees once that's how it looks also in the original video file:
What I want is to see her like in the first image but walking from left to right like it should be. Like in the second image her face point right !
This is the code I'm using:
int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
// bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
if (SaveToDisc)
{
String tempFile = _outFolder+ _frameId.ToString("D6") + ".bmp";
if (File.Exists(tempFile))
{
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
else
{
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
_frameId++;
}
else
{
if (Images == null)
Images = new List<Bitmap>();
Images.Add((Bitmap)bitmap.Clone());
}
}
return 0;
}
Now I rotate it once 180 degrees I tried to rotate it with another 90 degrees and then another 180 degrees but it didn't work.
I want to rotate the second image to the right in 90 degrees so I tried just:
bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
but it didn't do it.
How can I do it ?
Im trying now to use this function for the rotation:
public static Image RotateImage(Image img, float rotationAngle)
{
//create an empty Bitmap image
Bitmap bmp = new Bitmap(img.Width, img.Height);
//turn the Bitmap into a Graphics object
Graphics gfx = Graphics.FromImage(bmp);
//now we set the rotation point to the center of our image
gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
//now rotate the image
gfx.RotateTransform(rotationAngle);
gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
//set the InterpolationMode to HighQualityBicubic so to ensure a high
//quality image once it is transformed to the specified size
gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
//now draw our new image onto the graphics object
gfx.DrawImage(img, new Point(0, 0));
//dispose of our Graphics object
gfx.Dispose();
//return the image
return bmp;
}
Then im using it like this:
Bitmap t = new Bitmap(RotateImage(bitmap, 180));
t.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
But it dosent rotate it by 180 or 90 to the right ! Its making it mirror. If her face are pointing in the second image to the right i want to turn the image 90 degrees up to the right so she will stand with her face to the right !!! But instead im getting all the time that she is with the face to the left like a mirror.
Why ?
This is the class that extract the frames from the video file and save it to the hard disk:
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using DirectShowLib;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
namespace Polkan.DataSource
{
internal class WmvAdapter : ISampleGrabberCB, IDisposable
{
#region Fields
//public Image img;
private IFilterGraph2 _filterGraph;
private IMediaControl _mediaCtrl;
private IMediaEvent _mediaEvent;
private int _width;
private int _height;
private readonly string _outFolder;
private int _frameId;
private Label lbl1;
public bool done;
#endregion
#region Constructors and Destructors
public WmvAdapter(string file, string outFolder , Label lbl)
{
_outFolder = outFolder;
lbl1 = lbl;
try
{
SetupGraph(file);
}
catch
{
Dispose();
MessageBox.Show("A codec is required to load this video file. Please use http://www.headbands.com/gspot/ or search the web for the correct codec");
throw;
}
}
~WmvAdapter()
{
CloseInterfaces();
}
#endregion
public void Dispose()
{
CloseInterfaces();
}
public void Start()
{
int hr = _mediaCtrl.Run();
WaitUntilDone();
DsError.ThrowExceptionForHR(hr);
}
public void WaitUntilDone()
{
int hr;
const int eAbort = unchecked((int)0x80004004);
do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, out evCode);
} while
(hr == eAbort);
DsError.ThrowExceptionForHR(hr);
lbl1.ForeColor = Color.Red;
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
done = true;
}
/// <summary> build the capture graph for grabber. </summary>
private void SetupGraph(string file)
{
ISampleGrabber sampGrabber = null;
IBaseFilter capFilter = null;
IBaseFilter nullrenderer = null;
_filterGraph = (IFilterGraph2)new FilterGraph();
_mediaCtrl = (IMediaControl)_filterGraph;
_mediaEvent = (IMediaEvent)_filterGraph;
var mediaFilt = (IMediaFilter)_filterGraph;
try
{
// Add the video source
int hr = _filterGraph.AddSourceFilter(file, "Ds.NET FileFilter", out capFilter);
DsError.ThrowExceptionForHR(hr);
// Get the SampleGrabber interface
sampGrabber = new SampleGrabber() as ISampleGrabber;
var baseGrabFlt = sampGrabber as IBaseFilter;
ConfigureSampleGrabber(sampGrabber);
// Add the frame grabber to the graph
hr = _filterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);
// ---------------------------------
// Connect the file filter to the sample grabber
// Hopefully this will be the video pin, we could check by reading it's mediatype
IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
// Get the input pin from the sample grabber
IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0);
hr = _filterGraph.Connect(iPinOut, iPinIn);
DsError.ThrowExceptionForHR(hr);
// Add the null renderer to the graph
nullrenderer = new NullRenderer() as IBaseFilter;
hr = _filterGraph.AddFilter(nullrenderer, "Null renderer");
DsError.ThrowExceptionForHR(hr);
// ---------------------------------
// Connect the sample grabber to the null renderer
iPinOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0);
iPinIn = DsFindPin.ByDirection(nullrenderer, PinDirection.Input, 0);
hr = _filterGraph.Connect(iPinOut, iPinIn);
DsError.ThrowExceptionForHR(hr);
// Turn off the clock. This causes the frames to be sent
// thru the graph as fast as possible
hr = mediaFilt.SetSyncSource(null);
DsError.ThrowExceptionForHR(hr);
// Read and cache the image sizes
SaveSizeInfo(sampGrabber);
}
finally
{
if (capFilter != null)
{
Marshal.ReleaseComObject(capFilter);
}
if (sampGrabber != null)
{
Marshal.ReleaseComObject(sampGrabber);
}
if (nullrenderer != null)
{
Marshal.ReleaseComObject(nullrenderer);
}
GC.Collect();
}
}
private void SaveSizeInfo(ISampleGrabber sampGrabber)
{
// Get the media type from the SampleGrabber
var media = new AMMediaType();
int hr = sampGrabber.GetConnectedMediaType(media);
DsError.ThrowExceptionForHR(hr);
if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
{
throw new NotSupportedException("Unknown Grabber Media Format");
}
// Grab the size info
var videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
_width = videoInfoHeader.BmiHeader.Width;
_height = videoInfoHeader.BmiHeader.Height;
DsUtils.FreeAMMediaType(media);
GC.Collect();
}
private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
{
var media = new AMMediaType
{
majorType = MediaType.Video,
subType = MediaSubType.RGB24,
formatType = FormatType.VideoInfo
};
int hr = sampGrabber.SetMediaType(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
GC.Collect();
hr = sampGrabber.SetCallback(this, 1);
DsError.ThrowExceptionForHR(hr);
}
private void CloseInterfaces()
{
try
{
if (_mediaCtrl != null)
{
_mediaCtrl.Stop();
_mediaCtrl = null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
if (_filterGraph != null)
{
Marshal.ReleaseComObject(_filterGraph);
_filterGraph = null;
}
GC.Collect();
}
int ISampleGrabberCB.SampleCB(double sampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
return 0;
}
//add a boolean property to indicate the save-mode
public bool SaveToDisc { get; set; }
//the list for the bitmaps
public List<Bitmap> Images { get; set; }
int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
//bitmap.RotateFlip(RotateFlipType.RotateNoneFlipXY);
// bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
// Bitmap t = new Bitmap(RotateImage(bitmap, 180));
if (SaveToDisc)
{
String tempFile = _outFolder+ _frameId.ToString("D6") + ".bmp";
if (File.Exists(tempFile))
{
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
else
{
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
_frameId++;
}
else
{
if (Images == null)
Images = new List<Bitmap>();
Images.Add((Bitmap)bitmap.Clone());
}
}
return 0;
}
public static Image RotateImage(Image img, float rotationAngle)
{
//create an empty Bitmap image
Bitmap bmp = new Bitmap(img.Width, img.Height);
//turn the Bitmap into a Graphics object
Graphics gfx = Graphics.FromImage(bmp);
//now we set the rotation point to the center of our image
gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
//now rotate the image
gfx.RotateTransform(rotationAngle);
gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
//set the InterpolationMode to HighQualityBicubic so to ensure a high
//quality image once it is transformed to the specified size
gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
//now draw our new image onto the graphics object
gfx.DrawImage(img, new Point(0, 0));
//dispose of our Graphics object
gfx.Dispose();
//return the image
return bmp;
}
/*int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
MemoryStream myStream = new MemoryStream(1000000);
bitmap.Save(myStream, ImageFormat.Bmp);
//bitmap.Save(Path.Combine(_outFolder, _frameId + ".bmp"));
img = new Bitmap(myStream);
}
return 0;
}*/
}
}
And in Form1 im using the class like this:
private void button5_Click(object sender, EventArgs e)
{
button5.Enabled = false;
button1.Enabled = false;
wmv = new Polkan.DataSource.WmvAdapter(@"d:\VIDEO0040.3gp", sf,label2);
wmv.SaveToDisc = true;
wmv.Start();
if (wmv.done == true)
{
button1.Enabled = true;
}
}
I have tried with
bitmap1.RotateFlip(RotateFlipType.RotateNoneFlipX);
and seems to work as requested.
Actually, RotateFlipType.Rotate180FlipX
rotate the image of 180 degree, then flip on the X axis returning everything at the initial position.
Correct me if I'm wrong, I am not a graphic expert.
User contributions licensed under CC BY-SA 3.0