I am trying to upload an image (screenshot from desktop) to an SQL database as fast as possible. I would like to optimize my current procedure in terms of speed:
bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
byte[] imageBytes = convertImageToByteArray(bmpScreenshot);
MemoryStream mem = new MemoryStream(imageBytes);
using (Bitmap bmp1 = (Bitmap)Image.FromStream(mem))
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
ImageCodecInfo jgpEncoder = codecs[1];
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;
}
using (MemoryStream m = new MemoryStream())
{
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 23L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(m, jgpEncoder, myEncoderParameters);
using (Bitmap bmpLast = (Bitmap)Image.FromStream(m))
{
string query = "UPDATE ScreenCapture SET ScreenCapture=@Image,BroadcastTime=@BroadcastTime WHERE ID = 1";
SqlCommand sqlCommand = new SqlCommand(query, SQLconn);
ImageConverter converter = new ImageConverter();
byte[] beforeUpload = (byte[])converter.ConvertTo(bmpLast, typeof(byte[]));
sqlCommand.Parameters.AddWithValue("@Image", beforeUpload);
sqlCommand.Parameters.AddWithValue("@BroadcastTime", DateTime.Now);
SQLconn.Open();
sqlCommand.ExecuteNonQuery();
SQLconn.Close();
}
}
}
Profiling - Performance and Diagnostics in Visual Studio 2013
The method I posted has following usage:
- 40,8% -
byte[] imageBytes = convertImageToByteArray(bmpScreenshot);
- 10,4% -
MemoryStream mem = new MemoryStream(imageBytes);
- 37,8% -
mp1.Save(m, jgpEncoder, myEncoderParameters);
From captureUpload
which takes 93.6% in System.Windows.Forms.ni.dll:
- 69.9% - System.Drawing.ni.dll
- 26.8% -
convertImageToByteArray
- 8.8 -
PresentationFramework.ni.dll
convertImageToByteArray
takes 26.8% on return ms.ToArray()
.
It now takes me about 1 second to upload and download on client side, which is not so efficient in my case. If anyone have idea how this procedure is possible to make faster I would be glad to know. The image has around 60 KB, which is quite a lot.
-
\$\begingroup\$ Have you profiled your code? Which part takes the most time? \$\endgroup\$svick– svick2014年03月07日 16:58:43 +00:00Commented Mar 7, 2014 at 16:58
-
1\$\begingroup\$ Do you need to be able to see every pixel on the screen? If not, reduce the size of the image to half the height and width. Your image size will drop by about 75%. You can also lower the image quality of the JPEG by setting that attribute in the codec parameters (are you doing that with the 23 parameter?). \$\endgroup\$Adam Zuckerman– Adam Zuckerman2014年03月07日 20:38:50 +00:00Commented Mar 7, 2014 at 20:38
-
\$\begingroup\$ Which database are you using? Some are more efficient about BLOB storage than others. \$\endgroup\$Adam Zuckerman– Adam Zuckerman2014年03月07日 20:39:54 +00:00Commented Mar 7, 2014 at 20:39
-
\$\begingroup\$ @AdamZuckerman I'm using SQL Database to upload. I thought that it would be efficient to change the image quality then the image size but I will definetly try out! Thanks for recomendation! \$\endgroup\$Marek– Marek2014年03月07日 20:55:39 +00:00Commented Mar 7, 2014 at 20:55
-
1\$\begingroup\$ Are there absolute values on the profiling results apart from percents. What amount of that 1 sec is spent on establishing a connection from client to app server and from app server to DB server. \$\endgroup\$abuzittin gillifirca– abuzittin gillifirca2014年03月12日 08:44:41 +00:00Commented Mar 12, 2014 at 8:44
1 Answer 1
For graphic part :
I think Gdi++ of .NET framework is very slow. Mainly the Bitmap() construtor and Save() method.
If it's possible for screenshot, I recommend to use : Either directly gdi32.dll or (maybe, im not sure that is good idea) direct2d (benefits on hardware acceleration).
For transfert :
For your upload, run the transfert in other thread. (async or Delegate with BeginInvoke). After it depends on your internet connection speed.
However, i don't understand why you recreate your Bitmap object twice :
using (Bitmap bmp1 = (Bitmap)Image.FromStream(mem))
using (Bitmap bmpLast = (Bitmap)Image.FromStream(m))
Don't reload with Bitmap, create only one Bitmap for your screenshot, save it with encoding in memory stream and send memory stream to your database. With your memory stream you can get directly byte array with no conversion.
MemoryStream.Read(byte[] buffer, int offset, int count)