How to set desktop background *faster*? - c#

I have created a program which takes .GIF images, seperates them into seperate files. Then there is a timer which calls a method to read a file in the sequence and changes the wallpaper. I was just wondering if there is anyway I can make this process take less time. (It works, just not fast enough...)
Note:
I know this may be unchangeable for the Desktop is not made for this kind of thing, but I'm wondering if there is maybe even an untidy dirty hack in which I could accomplish this...
Windows Forms C# Code:
private void CreateAllFramesInTemp()
{
for (int i = 0; i < TOTALFRAMES; i++)
{
GIF.SelectActiveFrame(GIFDIMENSION, i);
GIF.Save(tempPath + i.ToString() + ".bmp", ImageFormat.Bmp);
}
updateInterval.Start();
}
private void updateInterval_Tick(object sender, EventArgs e)
{
if (currentWallpaperFrame < TOTALFRAMES)
{
currentWallpaperFrame += 1;
}
else
{
currentWallpaperFrame = 1;
}
//_-_-_-_-This sets the wallpaper-_-_-_-_//
SystemParametersInfo(20, 0, tempPath + (currentWallpaperFrame - 1).ToString() + ".bmp", 0x01 | 0x02);
}
Ask me any questions about the code if you don't know what a specific part is.

Related

Image from a bytearray failure

I have a function called: DisplayAndSaveImageFromByteArray.
by its name you probably understand what i am trying to do. In the bytearray the values are pixeldata. so like this 255,220,130,0, etc..
The size of the byte is the Width and the Height of the image times 4.
because it works with strides.
public void DisplayAndSaveImageFromByteArray(byte[] byteArray)
{
try{
byte[] data = new byte[width * height * 4];
int o = 0;
for (int io = 0; io < width * height; io++){
byte value = byteArray[io];
data[o++] = value;
data[o++] = value;
data[o++] = value;
data[o++] = 0;
}
unsafe
{
fixed (byte* ptr = data)
{
using (image = new Bitmap((int)width, (int)height, (int)width * 4,System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(ptr)))
{
image.Save(#"c:\\testmap\" + nextpicture + ".jpg", ImageFormat.Jpeg);
if (nextpicture >= 10)
{
pbCameraPreview.BeginInvoke(new InvokeDelegate(InvokeMethod));
}
nextpicture++;
}
}
}
}
catch (Exception ex){
MessageBox.Show(ex.ToString());
}
}
When i run this code it will work, but only if all values are the same for example: White (255,255,255) or Black (0,0,0).
it is able to deviate about 5 up and down in the RGB(A) values until it will stop working.
But as soon as the color of the image changes it will stop working without giving me an Exception of anything.
The only error/Exception i will get it if i leave it on for a minute and the VS will recognize that the code being executed is not doing anything and will give me a warning. > ContextSwitchDeadlock
What did i do wrong for it to crash?
and what is the solution for it?
for some reason it wont let me put on the using and namespace name...
(updated)Complete code:
public Form1()
{
InitializeComponent();
pbCameraPreview.Image = defImg;
}
#region Global
int ii;
object __p1;
EventArgs __p2;
string path;
Image defImg = Image.FromFile(#"c:\\testimg\def.jpg");
UInt32 width;
UInt32 height;
int nextpicture = 0;
FGNodeInfoContainer InfoContainer = new FGNodeInfoContainer();
FGNodeInfo NodeInfo = new FGNodeInfo();
FireWrap_CtrlCenter CtrlCenter;
enFireWrapResult Result;
UInt32 XSize = new UInt32();
UInt32 YSize = new UInt32();
UInt32 NodeCnt;
public delegate void InvokeDelegate();
Bitmap image;
CameraCode Cam = new CameraCode();
FGFrame Frame = new FGFrame();
FGUIntHL Guid = new FGUIntHL();
#endregion
public void CheckDirectory()
{
path = #"c:\\testmap\" + ii + "\\";
if (Directory.Exists(#"c:\\testmap\") == false)
{
Directory.CreateDirectory(#"c:\\testmap\");
}
if (Directory.Exists(path))
{
if (File.Exists(path + "0.Jpeg"))
{
ii++;
CheckDirectory();
}
}
else
{
Directory.CreateDirectory(path);
}
}
//Haal de images op
/// <param name="__p1"></param>
/// <param name="__p2"></param>
public void btStart_Click(object sender, EventArgs e)
{
Debug.WriteLine("btStart_Click is clicked");
// Init module
CtrlCenter = FireWrap_CtrlCenter.GetInstance();
Result = CtrlCenter.FGInitModule();
// Register frame start event
CtrlCenter.OnFrameReady += new FireWrap_CtrlCenter.FireWrapEvent(OnFrameReady);
// Get list of connected nodes
if (Result == enFireWrapResult.E_NOERROR)
{
Result = InfoContainer.FGGetNodeList();
NodeCnt = InfoContainer.Size();
// Print Nodecnt
Console.WriteLine(NodeCnt.ToString() + " camera found");
// Connect with first node
InfoContainer.GetAt(NodeInfo, 0);
Result = Cam.Connect(NodeInfo.Guid);
if (Result == enFireWrapResult.E_NOERROR)
{
Cam.m_Guid = NodeInfo.Guid;
}
// Set Format7 Mode0 Y8
if (Result == enFireWrapResult.E_NOERROR)
{
Result = Cam.SetParameter(enFGParameter.E_IMAGEFORMAT,
(uint)(((uint)enFGResolution.E_RES_SCALABLE << 16) |
((uint)enColorMode.E_CCOLORMODE_Y8 << 8) |
0));
}
if (Result != enFireWrapResult.E_NOERROR)
{
Result = Cam.SetParameter(enFGParameter.E_IMAGEFORMAT,
(uint)(((uint)enFGResolution.E_RES_SCALABLE << 16) |
((uint)enColorMode.E_CCOLORMODE_Y8 << 8) |
1));
}
// Start DMA logic
if (Result == enFireWrapResult.E_NOERROR)
Result = Cam.OpenCapture();
// Print device settings
Result = Cam.GetParameter(enFGParameter.E_XSIZE, ref XSize);
Result = Cam.GetParameter(enFGParameter.E_YSIZE, ref YSize);
Debug.WriteLine(Cam.DeviceAll + " [" + Cam.m_Guid.Low.ToString() + "] " + XSize + "x" + YSize);
width = XSize;
height = YSize;
// Start camera
if (Result == enFireWrapResult.E_NOERROR)
{
Result = Cam.StartDevice();
}
}
}
public void btStop_Click(object sender, EventArgs e)
{
// Stop the device
Cam.StopDevice();
// Close capture
Cam.CloseCapture();
// Disconnect before ExitModule
Cam.Disconnect();
// Exit module
CtrlCenter.FGExitModule();
}
/// <param name="__p1"></param>
/// <param name="__p2"></param>
public void OnFrameReady(object __p1, EventArgs __p2)
{
Debug.WriteLine("OnFrameReady is called");
FGEventArgs args = (FGEventArgs)__p2;
Guid.High = args.High;
Guid.Low = args.Low;
if (Guid.Low == Cam.m_Guid.Low)
{
Result = Cam.GetFrame(Frame, 0);
// Process frame, skip FrameStart notification
if (Result == enFireWrapResult.E_NOERROR & Frame.Length > 0)
{
byte[] data = new byte[Frame.Length];
// Access to frame data
if (Frame.CloneData(data))
{
DisplayAndSaveImageFromByteArray(data);
// Here you can start your image processsing logic on data
string debug = String.Format("[{6}] Frame #{0} length:{1}byte [ {2} {3} {4} {5} ... ]",
Frame.Id, Frame.Length, data[0], data[1], data[2], data[3], Cam.m_Guid.Low);
Debug.WriteLine(debug);
}
// Return frame to module as fast as posible after this the Frame is not valid
Result = Cam.PutFrame(Frame);
}
}
}
public void DisplayAndSaveImageFromByteArray(byte[] byteArray)
{
try{
byte[] data = new byte[width * height * 4];
int o = 0;
for (int io = 0; io < width * height; io++){
byte value = byteArray[io];
data[o++] = value;
data[o++] = value;
data[o++] = value;
data[o++] = 0;
}
unsafe
{
fixed (byte* ptr = data)
{
using (image = new Bitmap((int)width, (int)height, (int)width * 4,System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(ptr)))
{
image.Save(#"c:\\testmap\" + nextpicture + ".jpg", ImageFormat.Jpeg);
if (nextpicture >= 10)
{
pbCameraPreview.BeginInvoke(new InvokeDelegate(InvokeMethod));
}
nextpicture++;
}
}
}
}
catch (Exception ex){
MessageBox.Show(ex.ToString());
}
}
public void InvokeMethod()
{
pbCameraPreview.Image = Image.FromFile(#"c:\\testmap\" + (nextpicture -10) + ".jpg");
}
}
public class CameraCode : FireWrap_Camera
{
public FGUIntHL m_Guid;
}}
Threads running:
I recorded it for extra information:
https://www.youtube.com/watch?v=i3TxWRyZaIU
I'm not 100% sure that I have understood your problem, since it is not very clear the format of the input array and how do you have to format it before parsing it into the Bitmap variable... But here we go, I hope these tips can help you. If they don't, please try to provide some extra details on what you are trying to do.
First of all, if I have understood well, you should increase "io" and update the variable "value" each time you assign it to data[o++] in the main loop, otherwise you are assigning the same value to R, G and B pixels, which will always result in a shade of gray.
Secondly, I see a couple things in your code that are not very .net-ly... .Net provides already ways to load an image from a byte array, using Memory Streams and stuff. Take a look at How to create bitmap from byte array?
And be sure to indicate the proper format of your byte array image when instantiating the Bitmap or Image --> https://msdn.microsoft.com/en-us/library/system.drawing.imaging.pixelformat(v=vs.110).aspx
Regards.
If you have trouble posting your code in StackOverflow, make sure each line is indented by at least 4 spaces (mark the code in Visual Studio, press Tab, then copy it) and separated by any other paragraphs by at least one empty line. Alternatively add a line of three backticks (`) at the beginning and and of the code.
When looking at your code, it seems to me that you are using a third-party control inside a Windows Form and try to bind the event of it to one of your Windows Forms event handlers. In that case you have to be aware that Windows Forms expect that all events are handled single-threaded (in the Event Dispatch Thread), so you should check (Debug.WriteLine) in your OnFrameReady method if InvokeRequired is true and if yes you have to take a few precautions:
Never access any of the Form's internal members (like pbCameraPreview) without wrapping the call into Invoke or BeginInvoke. Keep in mind that every Invoke call will effectively block until the single event-dispatch thread is available, so it will cost you a lot of performance to do invoke synchronously.
When accessing your own members (like width, height or nextpicture), make sure you use appropriate locking to avoid situations where one thread/callback changes the value in a situation where you don't expect it. In particular, since you have multiple cams but only a single width/height variable, if the resolutions differ, one camera callback could change the width while the other camera callback has just allocated the byte array but before passing the width to the Bitmap constructor, most likely resulting in a hang, crash, or memory access violation. Avoid this by passing width and heigth as variables into your method instead of using the global ones.
Your form's event handler (btStart_Click) contains a busy-wait loop. This has multiple problems:
As stated before, every Form event handler runs in the same thread (and every Invoke as well). So as long as your loop is busy-waiting, no other events can be handled and the UI will be completely frozen. If code uses Invoke, that code will also eventually have to wait and be blocked, too.
Busy wait loops without any sleep code in it will cause your processor to run at the full cpu speed and it will eat 100% of that core, causing battery drain on notebooks and high power consumption and probably loud fans on other machines. Just don't do that.
In your concrete example, just remove the loop and move everything after the loop into the stop button instead. To avoid the problems with Windows Forms and invoking, I'd suggest to put all the image handling logic into a separate class that does its own locking (each instance of the class handling one camera only), and just call into it to start the process. You might even prefer to do your app as a Console application first to avoid any event-dispatching issues and later convert it to a Windows Forms application once it is working as you desire.

Adding percentage text to progressbar C#

I have a method that shows when a process bar is in execution and when is successfully completed.
I worked fine, but I would like to add a percentage showing a 100% if is complete and less if it got stuck some where.
I have made several research online but I could not adapt anything to the solution that I am looking for.
This is my code:
private void progressBar()
{
int i;
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
for (i = 0; i <= 100; i++)
{
progressBar1.Value = i;
}
}
I use the method call on my execution button by calling it with the follow:
progressBar();
Thanks
I have adjust the prograssBar method with the following lines.
The solution works.
Thanks
int percent = (int)(((double)progressBar1.Value / (double)progressBar1.Maximum) * 100);
progressBar1.Refresh();
progressBar1.CreateGraphics().DrawString(percent.ToString() + "%",
new Font("Arial", (float)8.25, FontStyle.Regular),
Brushes.Black,
new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
In order to implement the progress in your operation, the operation's length must be calculated first. if it's not possible, you can't show a progress bar for that operation. (maybe only a loading gif)
but if so, There is an interface (IProgress) which can help you implement the progress reports.
First thing you should know, You must do the main task on another thread, and report the progress to the UI Thread. a simple example of this work would be something like this.
Progress.cs
public class Progress<T> : IProgress<T>
{
private readonly Action<T> _progressAction;
public Progress(Action<T> action)
{
_progressAction = action;
}
public void Report(T value)
{
_progressAction?.Invoke(value);
}
}
Your code would be like this, in which the task starts after you click a button named ButtonBase
Progress<int> MyProgressObject { get; set; }
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MyProgressObject = new Progress<int>(ProgressAction);
ThreadPool.QueueUserWorkItem(TimeConsumingTask);
}
public void TimeConsumingTask(object state)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
MyProgressBar.Dispatcher.Invoke(() => ProgressAction(i));
}
}
public void ProgressAction(int progress)
{
MyProgressBar.Value = progress;
}
I know It might look difficult but this is the proper way of doing time consuming tasks and prevent UI block
If you use it as a part of backgroundworker it works perfectly
I added a Label in the middle of the progressbar
And i added last row in my bgw_ProgressChanged method
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
p_bar.Value = e.ProgressPercentage;
fnameLbl.Text = e.UserState.ToString();
percentLbl.Text = "%" + (e.ProgressPercentage).ToString();
}
ProgressPercentagevalue comes from the method below
foreach (var item in filebox1)
{
System.IO.File.Move(item, Path.Combine(destdir, Path.GetFileName(item)));
++counter;
int tmp = (int)((counter* 100) / totfiles);
bgw.ReportProgress(tmp, "File transfered : " + Path.GetFileName(item));
Thread.Sleep(100);
}
Totfiles is the number of files that I get from server.
Thread.Sleep(100) let's you see for a short time what is displayed with fnameLbl.Text
int total = ;
int val = ;
double createDivider = total / 100;
int percent = val / createDivider;
this value (percent) is the right percent '%' of total

Constructor of a user control load file from random location

I am creating a digital clock user control. Here is the code:
public partial class DigitalClockControl : UserControl
{
public DigitalClockControl()
{
InitializeComponent();
}
private static List<Image> Sprite;
private static Clock data;
public Clock Data
{
get { return DigitalClockControl.data; }
set { DigitalClockControl.data = value;
int min = data.Min;
int sec = data.Sec;
Min1.Image = Sprite[min / 10];
Min2.Image = Sprite[min % 10];
Sec1.Image = Sprite[sec / 10];
Sec2.Image = Sprite[sec % 10];
}
}
private void DigitalClockControl_Load(object sender, EventArgs e)
{
Sprite = new List<Image>();
LoadSprite();
data = new Clock();
}
private void LoadSprite()
{
string path = Directory.GetParent((Directory.GetParent((Directory.GetCurrentDirectory().ToString())).ToString())).ToString();
Image img;
for (int i = 0; i <= 9; ++i)
{
img = Image.FromFile(path + "\\" + i.ToString() + ".png");
Sprite.Add(img);
}
}
}
When I tried to drag this user control to the form, it raised an error like this:
Failed to create component 'DigitalClockControl'. The error messages follows:'System.IO.FileNotFoundException: D:\\0.png...
I don't know why it loads an image from D:\. All the images are at the path above. If I copy the image to D:\, the program works fine. I tried to go to the InitializeComponent() function but cannot file any code makes the program load the image.
Edit: solved by adding user control by code in Form.cs. Thank you very much for all your help.
You should place all images into debug\\bin\\images folder. so, when you install the application you can find all the images in Application Folder (Application.StartupPat + "\\Images").
CODE:
string path = Application.StartupPath + "\\Images";
Image img;
for (int i = 0; i <= 9; ++i)
{
img = Image.FromFile(path + "\\" + i.ToString() + ".png");
Sprite.Add(img);
}
Alternatively, you could use Assembly.GetExecutingAssembly() (that is the assembly containing your control) and use its Location Property to figure out where the root of your component is. You could put the images for your clock into a folder next to your assembly. By doing so, deployment would be easy and clear.

C# WMPLib Duration of a mp3

Im using WMPLib to make an easy mp3player in C#. Im almost done but theres one more thing I want to do.
I Would like to how far gone the song is and also, how much is left of the song.
using for example the progressbar.
thanks
Adam
private void timer1_Tick(object sender, EventArgs e)
{
double percent = 0;
if (mp.Length != 0)
percent = ((double) wplayer.controls.currentPosition / wplayer.controls.currentItem.duration);
progressBar1.Value = (int)(percent * progressBar1.Maximum);
}
I have an Idea , just try to add statusStrip to your Project Form , and try to add a ToolStripStatusLabel and ToolStripProgressBar to it, and then you can use this simple code , it Works 100% :
public void Sound_Progress(ToolStripStatusLabel l1, ToolStripProgressBar psb)
{
//NASSIM LOUCHANI
int i = Convert.ToInt32(Player.controls.currentItem.duration);
int j = Convert.ToInt32(Player.controls.currentPosition);
int Defrence = (i-j);
l1.Text = Player.controls.currentPositionString + " | " + Player.controls.currentItem.durationString;
psb.Maximum = i;
psb.Minimum = 0;
if (Defrence == i)
psb.Value = i;
else if (Defrence != i)
psb.Value = Defrence;
else if (Defrence == 0)
l1.Text = "";
}
And don't forget to add a Timer to your Project Form and put the Sound_Progress(your ToolStripStatusLabel, your ToolStripProgressBar) into your Timer_Tick() Event .
Thank you !

Creating a Huge Dummy File in a Matter of Seconds in C#

I want to create a huge dummy file say 1~2 GBs in matter of seconds.
here is what I've written in C#:
file.writeallbytes("filename",new byte[a huge number]);
and another way with indicating the status, was like following:
long FSS = din.TotalFreeSpace;
long segments = FSS / 10000;
long last_seg = FSS % 10000;
BinaryWriter br = new BinaryWriter(fs);
for (long i = 0; i < segments; i++)
{
br.Write(new byte[10000]);
this.label2.Text = "segments write :" + i.ToString() + "\r\n" + "segments remain :" + ((segments-i)+1).ToString();
Application.DoEvents();
}
br.Write(new byte[last_seg]);
this.label2.Text += "\r\nDone!";
br.Close();
where din is Disk Information object
well with these two approach it takes something like 2 or more minutes to write such a big but dummy file. Is there any other faster way for doing so?
Simply create the file, seek to a suitably large offset, and write a single byte:
FileStream fs = new FileStream(#"c:\tmp\huge_dummy_file", FileMode.CreateNew);
fs.Seek(2048L * 1024 * 1024, SeekOrigin.Begin);
fs.WriteByte(0);
fs.Close();
This will yield a 2GB file with basically unpredictable contents, which should be fine for your purposes.
If you don't care about the contents, then by far the fastest way I know of is this - it is practically instant:
private void CreateDummyFile(string fileName, long length)
{
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
fileStream.SetLength(length);
}
}
If you just need a FileStream, you could use FileStream.SetLength. That will get you a stream which is 2 GB long. Then you can write the final byte at an arbitrary position of your choice. But the contents will be undefined.
If you're trying to actually create a file on the disk, yes, you'll need to actually write its contents. And yes, hard disks are going to be slow; something like a 1 GB/min write speed isn't totally ridiculous. Sorry -- that's physics!
Why did you not use the BackgroundWorker class to achieve this, as you can pass anything into the method ReportProgress to indicate the status report. See the example below:
private BackgroundWorker bgWorker;
public Form1()
{
InitializeComponent();
bgWorker = new BackgroundWorker();
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.RunWorkerAsync();
}
void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.label2.Text = "Done";
}
void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MyStatus myProgressStatus = (MyStatus)e.UserState;
this.label2.Text = string.Format("segments write : {0}" + Environment.Newline + "Segments Remain: {1}", myProgressStatus.iWritten, myProgressStatus.iRemaining);
}
void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
long FSS = din.TotalFreeSpace;
long segments = FSS / 10000;
long last_seg = FSS % 10000;
BinaryWriter br = new BinaryWriter(fs);
for (long i = 0; i < segments; i++)
{
br.Write(new byte[10000]);
bgWorker.ReportProgress(i.ToString(), new MyStatus(i, ((segments-i) + 1)));
}
br.Write(new byte[last_seg]);
br.Close();
}
public class MyStatus{
public int iWritten;
public int iRemaining;
public MyStatus(int iWrit, int iRem){
this.iWritten = iWrit;
this.iRemaining = iRem;
}
}
}
This is a rough draft...
I could be wrong but you will probably find that it's impossible to create a file that large that quickly as there will be a bottleneck in the I/O writing process.
However in your code above the Applciation.DoEvents will be slowing things down. Also any repainting of the screenthis.label2.Text = will cause a slight slow down.

Categories