title: Performance optimization of multiple rotating images
body: <p>I'm working on a project in C# windows forms where I'm using pictureboxes to display multiple tachometers. </p>
  
  <p>Each picturebox consists of a background image and an image. The background image is static, but the image (displaying the actual indicator) is rotated and updated a couple of times per second.</p>
  
  <p>Background image: <a href="https://i.stack.imgur.com/FBsKI.jpg" rel="nofollow noreferrer">http://i.stack.imgur.com/FBsKI.jpg</a></p>
  
  <p>Fron image: <a href="https://i.stack.imgur.com/T0nJU.jpg" rel="nofollow noreferrer">http://i.stack.imgur.com/T0nJU.jpg</a></p>
  
  <p>It works well as long as I have one or two tachometers running simultaneously, but when I add more it starts to lag a lot.</p>
  
  <p>Here is the code I use for updating the picturebox:</p>
  
  <pre><code>private void timer4_Tick(object sender, EventArgs e)
      {
          Bitmap image = RotateImage(indicatorImg, i++, false, true, Color.Transparent);
          pictureBox4.Image = image;
      }
  </code></pre>
  
  <p>The RotateImage function I'm using (Credit to RenniePet at <a href="https://stackoverflow.com/a/16027561/3660713">https://stackoverflow.com/a/16027561/3660713</a>): </p>
  
  <pre><code>public static Bitmap RotateImage(Image inputImage, float angleDegrees, bool upsizeOk,
                                       bool clipOk, Color backgroundColor)
      {
          lock (lockObject)
          {
              // Test for zero rotation and return a clone of the input image
              if (angleDegrees == 0f)
                  return (Bitmap)inputImage.Clone();
  
              // Set up old and new image dimensions, assuming upsizing not wanted and clipping OK
              int oldWidth = inputImage.Width;
              int oldHeight = inputImage.Height;
              int newWidth = oldWidth;
              int newHeight = oldHeight;
              float scaleFactor = 1f;
  
              // If upsizing wanted or clipping not OK calculate the size of the resulting bitmap
              if (upsizeOk || !clipOk)
              {
                  double angleRadians = angleDegrees * Math.PI / 180d;
  
                  double cos = Math.Abs(Math.Cos(angleRadians));
                  double sin = Math.Abs(Math.Sin(angleRadians));
                  newWidth = (int)Math.Round(oldWidth * cos + oldHeight * sin);
                  newHeight = (int)Math.Round(oldWidth * sin + oldHeight * cos);
              }
  
              // If upsizing not wanted and clipping not OK need a scaling factor
              if (!upsizeOk &amp;&amp; !clipOk)
              {
                  scaleFactor = Math.Min((float)oldWidth / newWidth, (float)oldHeight / newHeight);
                  newWidth = oldWidth;
                  newHeight = oldHeight;
              }
  
              // Create the new bitmap object. If background color is transparent it must be 32-bit, 
              //  otherwise 24-bit is good enough.
              Bitmap newBitmap = new Bitmap(newWidth, newHeight, backgroundColor == Color.Transparent ?
                                               PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb);
              newBitmap.SetResolution(inputImage.HorizontalResolution, inputImage.VerticalResolution);
  
              // Create the Graphics object that does the work
              using (Graphics graphicsObject = Graphics.FromImage(newBitmap))
              {
                  graphicsObject.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                  graphicsObject.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                  graphicsObject.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  
                  // Fill in the specified background color if necessary
                  if (backgroundColor != Color.Transparent)
                      graphicsObject.Clear(backgroundColor);
  
                  // Set up the built-in transformation matrix to do the rotation and maybe scaling
                  graphicsObject.TranslateTransform(newWidth / 2f, newHeight / 2f);
  
                  if (scaleFactor != 1f)
                      graphicsObject.ScaleTransform(scaleFactor, scaleFactor);
  
                  graphicsObject.RotateTransform(angleDegrees);
                  graphicsObject.TranslateTransform(-oldWidth / 2f, -oldHeight / 2f);
  
                  // Draw the result 
                  graphicsObject.DrawImage(inputImage, 0, 0);
              }
  
              return newBitmap;
          }
      }
  </code></pre>
  
  <p>Any ideas on how to improve performance? Is there a better way to do this?</p>