I am currently trying to draw just a section of a BufferedImage that is within the bounds of a Rectangle on the fly. The image gets moved, and thus the size of the image in the rectangle changes.
Visual depiction:
Currently, this is what I have and it works great with a low res image. But if I scale the minimap up, this becomes very inefficient and causes lag
private BufferedImage extractPixels() {
int[] imagePixels = new int[scaledImage.getWidth() * scaledImage.getHeight()];
scaledImage.getRGB(0, 0, scaledImage.getWidth(), scaledImage.getHeight(), imagePixels,
0, scaledImage.getWidth());
int maxX = 0, maxY = 0;
boolean first = false;
for (int y = 0; y < scaledImage.getHeight(); y++) {
for (int x = 0; x < scaledImage.getWidth(); x++) {
int px = (int)(this.x + x);
int py = (int)(this.y + y);
if (viewingArea.contains(px, py)) {
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
if (!first) {
imageX = x;
imageY = y;
first = true;
}
}
}
}
int xCount = maxX - imageX;
int yCount = maxY - imageY;
if (imageX < 0 || imageX > scaledImage.getWidth() || imageX + xCount > scaledImage.getWidth()) return null;
if (imageY < 0 || imageY > scaledImage.getHeight() || imageY + yCount > scaledImage.getHeight()) return null;
return scaledImage.getSubimage(imageX, imageY, xCount, yCount);
}
In Render loop:
public void Render(PixelRenderer renderer) {
BufferedImage image = extractPixels();
if (image != null) renderer.renderImage(image, x + imageX, y + imageY);
}
Is there a way to do this more efficiently, so that re-scaling has less of an effect on performance?
Fixed by calculating where the image should subimage from, and the size of the subimage dependent on the position of the main image.
private BufferedImage extractPixels() {
double xp = viewingArea.x - this.x;
double yp = viewingArea.y - this.y;
double iw = viewingArea.width;
double ih = viewingArea.height;
int rightBound = scaledImage.getWidth() - viewingArea.width;
int bottomBound = scaledImage.getHeight() - viewingArea.height;
if (xp < 0) {
xp = 0;
iw = viewingArea.width - (this.x - viewingArea.x);
imageX = viewingArea.x + (viewingArea.width - (int)iw);
} else if (xp >= 0 && xp < rightBound) {
xp -= dx;
iw -= dx;
imageX = viewingArea.x;
}
if (xp >= rightBound) {
iw = viewingArea.width - ((int)xp - (scaledImage.getWidth() - viewingArea.width));
imageX = viewingArea.x;
}
if (yp < 0) {
yp = 0;
ih = viewingArea.height - (this.y - viewingArea.y);
imageY = viewingArea.x + (viewingArea.height - (int)ih);
} else if (yp >= 0 && yp < bottomBound) {
yp -= dy;
ih -= dy;
imageY = viewingArea.y;
}
if (yp >= bottomBound) {
ih = viewingArea.height - ((int)yp - (scaledImage.getHeight() - viewingArea.height));
imageY = viewingArea.y;
}
if (iw < 0) iw = Math.abs(iw);
if (ih < 0) ih = Math.abs(ih);
if (xp < 0) xp = Math.abs(xp);
if (yp < 0) yp = Math.abs(yp);
BufferedImage result = new BufferedImage((int)iw, (int)ih, BufferedImage.TYPE_INT_RGB);
try {
result = scaledImage.getSubimage((int)xp, (int)yp, (int)iw, (int)ih);
} catch (Exception e) {
//TODO: Log to game engine something bad has happened
e.printStackTrace();
}
return result;
}