0

I am trying to take multiple screenshots and save them to a file. However, screenshots are taken decently often, and in order to not lose any of them, my current program will simply create a new file for every screenshot. Ideally, the program would simply "append" the most recent screenshot onto a single file every time.

Here is the code:

static Rectangle bounds = Screen.GetBounds(Point.Empty);
static Size rectSize = new Size(bounds.Width, bounds.Height);
    public static void takeScreenshot(string path, int iteration, string filetype)
    {
        using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
        {
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                g.CopyFromScreen(Point.Empty, Point.Empty, new Size
                    (rectSize.Width * iteration, rectSize.Height));
            }
            bitmap.Save(path + filetype);
        }
    }

iteration was the amount of times the method has been called. I was trying to just shift the next screenshot over by one screenshot's width while keeping every other screenshot, but it seems to overwrite the file anyways. Is it possible to do this?

robbbbin
  • 13
  • 1
  • 1
  • 3
  • You're going to have to read the saved bitmap, create a new bitmap that contains your saved bitmap and new screenshot and then save it to file. – JohanP Aug 20 '18 at 02:30
  • This is not going to work in any respect, and even if you get it to work, you will run out of gdi memory trying to create a bitmap like that. you could possibly do this in raw bytes, but even then you will have to keep rewriting the file to insert the new width on the the scan line. Save your self some hassle, and just store then in different files, they will be easier to work with – TheGeneral Aug 20 '18 at 02:58
  • You could save a multi-page TIFF image. An example here:[Convert bitmaps to one multipage TIFF image](https://stackoverflow.com/questions/398388/convert-bitmaps-to-one-multipage-tiff-image-in-net-2-0?answertab=active#tab-top). APing is not really supported in .Net, but there's a libray here: [APNG.NET - GitHub](https://github.com/xupefei/APNG.NET). Think about it twice. (`System.Windows.Media.Imaging` make it easier to work with multi-frames images.) – Jimi Aug 20 '18 at 03:37
  • Looks like you are trying to make a video, not image. – Barmak Shemirani Aug 20 '18 at 04:31

2 Answers2

0

Try this..

string n = string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now);
bitmap.Save(path + n + filetype);
farrukh aziz
  • 162
  • 1
  • 2
  • 9
  • You do understand that your code just creates a new file for every screenshot? Which is exactly what the OP does *not* want. – Markus Deibel Aug 20 '18 at 05:22
0

Like TheGeneral said, you will run out of memory quickly. And every time the file grows it has a chance of needing to be moved on disc wearing down your drives.

Also, opening and viewing huge image files can be very slow, your computer will not be able to handle it very quickly.

But here it is, maybe at least the AppendImage function could be used for something like generating particle sprite strips in games or something.

If you're appending a screenshot, I wouldn't append more than maybe 10 times, with 1080P monitor.

    public enum AppendLocation
    {
        Before,
        After
    }

    void AppendScreenToFile(string filename, AppendLocation appendLocation = AppendLocation.After)
    {
        Rectangle bounds = Screen.PrimaryScreen.Bounds;

        using (Bitmap screenShot = new Bitmap(bounds.Width, bounds.Height))
        {
            using (Graphics g = Graphics.FromImage(screenShot))
            {
                g.CopyFromScreen(UpperLeftSource, Point.Empty, bounds.Size);
            }

            if (!File.Exists(filename))
            {
                screenShot.Save(filename, ImageFormat.Png);
                return;
            }

            //Not using Image.FromFile as it blocks saving.
            Image onDisc;
            using (Stream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
                onDisc = Image.FromStream(fs);

            using (Image appended = appendLocation == AppendLocation.Before ? AppendImage(screenShot, onDisc) : AppendImage(onDisc, screenShot))
                appended.Save(filename, ImageFormat.Png);
        }
    }


    public enum AppendAxis
    {
        Vertical,
        Horizontal
    }

    Bitmap AppendImage(Image image, Image append, AppendAxis axis = AppendAxis.Vertical)
    {
        Bitmap bitmap;
        Rectangle destinationRect;
        RectangleF imageBounds = new Rectangle(0, 0, image.Width, image.Height);
        RectangleF appendRect = new Rectangle(0, 0, append.Width, append.Height);

        pictureBox_Item4.BackgroundImage = image;
        pictureBox_Item3.BackgroundImage = append;

        switch (axis)
        {
            case AppendAxis.Vertical:                    
                destinationRect = new Rectangle(0, image.Height, append.Width, append.Height);
                bitmap = new Bitmap(image.Width, image.Height + append.Height);
                break;
            case AppendAxis.Horizontal:
                destinationRect = new Rectangle(image.Width, 0, append.Width, append.Width);
                bitmap = new Bitmap(image.Width + append.Width, image.Height);
                break;
            default:
                throw new ArgumentException("AppendAxis is invalid.");
        }

        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.DrawImage(image, imageBounds, imageBounds, GraphicsUnit.Pixel);
            g.DrawImage(append, destinationRect, appendRect, GraphicsUnit.Pixel);
            return bitmap;
        }
    }
Addio
  • 89
  • 1
  • 6