Skip to content

Commit

Permalink
screenshot: image capture: support insets on client frame
Browse files Browse the repository at this point in the history
The insets include the native client border, which results in an 8px
alpha border on the image. Remove the insets from the screenshot.

With j2d scaling the image size is an extra pixel wide and the client
position within the frame is an extra pixel down (with gpu). I think
this is due to the rounding of getScaledValue(), which was originally
copied from jogl.
  • Loading branch information
Adam- committed Jan 21, 2024
1 parent b6939a0 commit c9e0e9b
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1847,7 +1847,7 @@ private GpuIntBuffer bufferForTriangles(int triangles)

private int getScaledValue(final double scale, final int value)
{
return (int) (value * scale + .5);
return (int) (value * scale);
}

private void glDpiAwareViewport(final int x, final int y, final int width, final int height)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.awt.Image;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.SystemTray;
import java.awt.Taskbar;
Expand Down Expand Up @@ -94,7 +95,6 @@
import net.runelite.api.Constants;
import net.runelite.api.GameState;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.widgets.ComponentID;
import net.runelite.api.widgets.Widget;
Expand Down Expand Up @@ -875,7 +875,7 @@ public void setCursor(final BufferedImage image, final String name)
return;
}

final java.awt.Point hotspot = new java.awt.Point(0, 0);
final Point hotspot = new Point(0, 0);
final Cursor cursorAwt = Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name);
defaultCursor = cursorAwt;
setCursor(cursorAwt);
Expand Down Expand Up @@ -917,14 +917,18 @@ public Point getCanvasOffset()
final Canvas canvas = ((Client) client).getCanvas();
if (canvas != null)
{
final java.awt.Point point = SwingUtilities.convertPoint(canvas, 0, 0, frame);
return new Point(point.x, point.y);
return SwingUtilities.convertPoint(canvas, 0, 0, frame);
}
}

return new Point(0, 0);
}

public Insets getInsets()
{
return frame.getInsets();
}

/**
* Paint UI related overlays to target graphics
* @param graphics target graphics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import com.google.common.base.Strings;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.datatransfer.Clipboard;
Expand All @@ -49,7 +51,6 @@
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.Point;
import net.runelite.client.Notifier;
import static net.runelite.client.RuneLite.SCREENSHOT_DIR;
import net.runelite.client.config.RuneScapeProfileType;
Expand Down Expand Up @@ -115,11 +116,15 @@ public BufferedImage addClientFrame(Image image)
final AffineTransform transform = OSType.getOSType() == OSType.MacOS ? new AffineTransform() :
clientUi.getGraphicsConfiguration().getDefaultTransform();

// on Windows the insets are the window border
Insets insets = clientUi.getInsets();
transform.translate(-insets.left, -insets.top);

// scaled client dimensions
int clientWidth = getScaledValue(transform.getScaleX(), clientUi.getWidth());
int clientHeight = getScaledValue(transform.getScaleY(), clientUi.getHeight());
int screenshotWidth = getScaledValue(transform.getScaleX(), clientUi.getWidth() - insets.left - insets.right);
int screenshotHeight = getScaledValue(transform.getScaleY(), clientUi.getHeight() - insets.top - insets.bottom);

final BufferedImage screenshot = new BufferedImage(clientWidth, clientHeight, BufferedImage.TYPE_INT_ARGB);
final BufferedImage screenshot = new BufferedImage(screenshotWidth, screenshotHeight, BufferedImage.TYPE_INT_ARGB);

Graphics2D graphics = (Graphics2D) screenshot.getGraphics();
AffineTransform originalTransform = graphics.getTransform();
Expand All @@ -138,8 +143,11 @@ public BufferedImage addClientFrame(Image image)

// Find the position of the canvas inside the frame
final Point canvasOffset = clientUi.getCanvasOffset();
final int gameOffsetX = getScaledValue(transform.getScaleX(), canvasOffset.getX());
final int gameOffsetY = getScaledValue(transform.getScaleY(), canvasOffset.getY());
canvasOffset.x -= insets.left;
canvasOffset.y -= insets.top;

final int gameOffsetX = getScaledValue(transform.getScaleX(), (int) canvasOffset.getX());
final int gameOffsetY = getScaledValue(transform.getScaleY(), (int) canvasOffset.getY());

// Draw the original screenshot onto the new screenshot
graphics.setTransform(originalTransform); // the original screenshot is already scaled
Expand All @@ -151,7 +159,7 @@ public BufferedImage addClientFrame(Image image)

private static int getScaledValue(final double scale, final int value)
{
return (int) (value * scale + .5);
return (int) (value * scale);
}

/**
Expand Down

0 comments on commit c9e0e9b

Please sign in to comment.