Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-33383

Lag while taking screenshot with F2 in singleplayer


    • Icon: Bug Bug
    • Resolution: Fixed
    • Minecraft 1.6.4, Minecraft 13w39b, Minecraft 13w41a, Minecraft 1.8, Minecraft 1.8.1, Minecraft 1.8.2-pre1, Minecraft 1.8.3, Minecraft 1.8.9, Minecraft 15w51b, Minecraft 1.9 Pre-Release 4, Minecraft 1.9, Minecraft 1.10.2, Minecraft 16w32b, Minecraft 16w43a, Minecraft 16w44a, Minecraft 1.11 Pre-Release 1, Minecraft 1.11, Minecraft 16w50a, Minecraft 1.11.2, Minecraft 17w06a, Minecraft 1.12.1, Minecraft 1.12.2, Minecraft 17w43a, Minecraft 17w43b, Minecraft 17w45b, Minecraft 17w46a, Minecraft 17w47a, Minecraft 17w47b, Minecraft 17w48a, Minecraft 17w50a
    • Confirmed

      The bug

      While taking a screenshot using the in-game F2 key, the game freezes for a second and does not take an accurate screenshot.

      Code analysis

      The reason why this is happening is because saving the screenshot is not done by a seperate thread. This means the lag time is determined by the writing speed of your harddrive.
      Another reason which has probably a rather small impact is that in case frame buffering is enabled Minecraft iterates over all pixels in the screenshot and sets them in a BufferedImage. I do not see any advantage of this.
      Here is a "fix" that solves this problem, however the ScreenshotSavingThread is only used as a local variable to demonstrate that it solves the problem. It should be rather in the class itself and also set the error message in case it fails:
      saveScreenshot(File p_148259_0_, String p_148259_1_, int p_148259_2_, int p_148259_3_, Framebuffer p_148259_4_) method of the net.minecraft.util.ScreenShotHelper class (MCP 1.8 names)

      saveScreenshot(File p_148259_0_, String p_148259_1_, int p_148259_2_, int p_148259_3_, Framebuffer p_148259_4_)
      // Is there any advantage from this?
      if (OpenGlHelper.isFramebufferEnabled())
      	var7 = new BufferedImage(p_148259_4_.framebufferWidth, p_148259_4_.framebufferHeight, 1);
      	int var8 = p_148259_4_.framebufferTextureHeight - p_148259_4_.framebufferHeight;
      	for (int var9 = var8; var9 < p_148259_4_.framebufferTextureHeight; ++var9)
      		for (int var10 = 0; var10 < p_148259_4_.framebufferWidth; ++var10)
      			var7.setRGB(var10, var9 - var8, pixelValues[var9 * p_148259_4_.framebufferTextureWidth + var10]);
      	var7 = new BufferedImage(p_148259_2_, p_148259_3_, 1);
      	var7.setRGB(0, 0, p_148259_2_, p_148259_3_, pixelValues, 0, p_148259_2_);
      File var12;
      if (p_148259_1_ == null)
      	var12 = getTimestampedPNGFileForDirectory(var5);
      	var12 = new File(var5, p_148259_1_);
      // Create an empty file to make sure a ScreenshotSavingThreads do not override it by accident
      //ImageIO.write(var7, "png", var12);
      class ScreenshotSavingThread extends Thread {
      	private final BufferedImage bufferedImage;
      	private final File file;
      	private ScreenshotSavingThread(BufferedImage bufferedImage, File file) {
      		this.bufferedImage = bufferedImage;
      		this.file = file;
      	public void run() {
      		try {
      			ImageIO.write(bufferedImage, "png", file);
      		} catch (IOException e) {
      			// TODO Print the error message in chat and in the log
      new ScreenshotSavingThread(var7, var12).start();
      Flaws with this design
      • Stopping Minecraft could cause half-finished screenshots (unlikely); thread could be non-daemon
      • Taking screenshots to often results in a OutOfMemoryError (unlikely, that would need with 500KB per screenshot and 500MB allocated RAM about 1000 ScreenshotSavingThreads running at once)
      • Reporting error or success would have to be synchronized and would appear delayed which could be confusing

            grum [Mojang] Grum (Erik Broes)
            greatmastermario Andrew Thomas
            23 Vote for this issue
            13 Start watching this issue