I have an application in which i want to take the screenshot of the game screen and save it as an image and upload to Facebook. I am using Libgdx and my focus is android.
Can anyone help me that how to take screenshot of the game screen programmatically and save it as an image ??
It is now fairly easy. Libgdx provides an example, which can be found on the page Taking a Screenshot.
I had to add one statement to get it working. The image could not be saved directly to /screenshot1.png. Simply prepend Gdx.files.getLocalStoragePath().
Source Code:
public class ScreenshotFactory {
private static int counter = 1;
public static void saveScreenshot(){
try{
FileHandle fh;
do{
fh = new FileHandle(Gdx.files.getLocalStoragePath() + "screenshot" + counter++ + ".png");
}while (fh.exists());
Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
PixmapIO.writePNG(fh, pixmap);
pixmap.dispose();
}catch (Exception e){
}
}
private static Pixmap getScreenshot(int x, int y, int w, int h, boolean yDown){
final Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(x, y, w, h);
if (yDown) {
// Flip the pixmap upside down
ByteBuffer pixels = pixmap.getPixels();
int numBytes = w * h * 4;
byte[] lines = new byte[numBytes];
int numBytesPerLine = w * 4;
for (int i = 0; i < h; i++) {
pixels.position((h - i - 1) * numBytesPerLine);
pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
}
pixels.clear();
pixels.put(lines);
}
return pixmap;
}
}
Simple solution:
Image screenShot = new Image(ScreenUtils.getFrameBufferTexture());
I just want to add somethings here.
When taking a screeenShot we need to consider blackbars and resized windows too. If you don't have a viewPort (for mobile devices), just replace gutter dimensions with 0.
Here is how you properly take a fullScreen-screenShot:
final Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(
MyGdxGame.viewport.getLeftGutterWidth(),
MyGdxGame.viewport.getTopGutterHeight(),
Gdx.graphics.getWidth() - MyGdxGame.viewport.getLeftGutterWidth() - MyGdxGame.viewport.getRightGutterWidth(),
Gdx.graphics.getHeight() - MyGdxGame.viewport.getTopGutterHeight() - MyGdxGame.viewport.getBottomGutterHeight());
Then you could save a pixmap using PixmapIO. https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/PixmapIO.html
NOTE: Note that y is not bottom gutter but the top one. Because of the difference in coordinate system. That also why the image comes upside down.
Also you could flip the pixmap (Only if you are not going to turn it to a Texture and then Sprite) using the code in the link below.
https://stackoverflow.com/a/19746741/2205307
You want to create a FrameBuffer, frameBuffer.begin(), render everything, frameBuffer.end().
You can then get the Pixmap. This has everything you need to save it as any image file.
Thanks i solved it using the link http://code.google.com/p/libgdx-users/wiki/Screenshots?
but used PixmapIO.wirtePNG ( pixmap , fileHandle ) instead of PNG.toPNG because it gives error that there is no PNG class.
Thanks to Stick2 who helped me.
Related
a have a problem with scaling images up. I have a png file that looks like this:
raw png
The image is 8px * 8px and has some red straight lines on it.
But when i draw this image with java and scale it up this happens: java image
And as you can barly see, the line is not exactly straight. It is always one pixel off and makes this kind of wavy shape. If the image gets drawn somewhere else on the frame the "waves" are somewhere else. The image is rotated 90° but I tested it without rotation and it was still there. Apart from this I do need rotated images.
Is there any way to fix this? I enabled text-antialiasing in the same Graphics2D object. Is there also some sort of anitaliasing for this?
Code
private void loadImage(String path, int field, int imageNumber) {
BufferedImage image;
image = new Resource().readImg(path);
images[field][imageNumber][0] = image;
images[field][imageNumber][1] = rotateClockwise90(image);
images[field][imageNumber][2] = rotateClockwise90(rotateClockwise90(image));
images[field][imageNumber][3] = rotateClockwise90(rotateClockwise90(rotateClockwise90(image)));
}
private BufferedImage rotateClockwise90(BufferedImage src) {
int width = src.getWidth();
int height = src.getHeight();
BufferedImage dest = new BufferedImage(height, width, src.getType());
Graphics2D graphics2D = dest.createGraphics();
graphics2D.translate((height - width) / 2, (height - width) / 2);
graphics2D.rotate(Math.PI / 2, height / 2, width / 2);
graphics2D.drawRenderedImage(src, null);
return dest;
}
When the program starts I load the image I rotate it in all 4 directions, so I don't have to do this over and over again while the program is running.
public BufferedImage getTile(int type, int part, int rotation) {
return images[type][part][rotation];
}
And then all I have to do is calling this get method and draw the image:
g2d.drawImage(tiles.getShipTile(type, part, rotation), x, y, null);
I actually found a way to avoid these weird pixels but this method makes the image a little bit blurry.
Instead of using
g2d.drawImage(img, x, y, width, height, null);
you can simply use
g2d.drawImage(img.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING), x, y, null);
which does basically the same thing but wehn I scale it up it uses this smooth making key.
I tried this and noticed that its not verry comfortable because it lags a lot.
So I just scale it up in the beginning when I also rotate the images.
As I said this method is a bit blurry but if there are no other ways avoiding this problem I have to get use of this. You almost can't see the blur, so this would be an option for me.
What is the proper way to extend the background in top down game? I used LibGdx framework. Any idea or tutorial for top down game.My background is in PNG format and screen of 720x1280 portrait.I had a problem in extending the background.I want the camera follow the character and the background will extend. How could I do that? Here is the Screen shot of
https://i.stack.imgur.com/jl03R.png
Here is my code
To display background I used this
//background
Background = new Texture(Gdx.files.internal("floor.png")); //File from assets folder
Background.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
bgsprite = new Sprite(Background);
In render
spriteBatch.draw(Background,0,100,0, srcy, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
srcy +=3;
The background is scrolling but the camera don't follow the player(cat)
Source code for GameScreen
http://pastebin.com/Dxfx9f65
Thank's and Advance any help or suggestion are much appreciated. :)
Use two identical texture background. Each the size of the screen It can be the same file. It is important that are docked vertically. Move of at the same time. Alternately changing with each other.
Sample code:
declaration:
Texture background1, background2;
SpriteBatch batch;
float yMax, yCoordBg1, yCoordBg2;
final int BACKGROUND_MOVE_SPEED = 100; // pixels per second. Put your value here.
creation:
Background1 = new Texture(Gdx.files.internal("floor.png"));
Background2 = new Texture(Gdx.files.internal("floor.png")); // identical
yMax = 1280;
yCoordBg1 = yMax*(-1); yCoordBg2 = 0;
in method render:
yCoordBg1 += BACKGROUND_MOVE_SPEED * Gdx.graphics.getDeltaTime();
yCoordBg2 = yCoordbg1 + yMax; // We move the background, not the camera
if (yCoordBg1 >= 0) {
yCoordBg1 = yMax*(-1); yCoordBg2 = 0;
}
batch.begin();
batch.draw(background1, 0, yCoordBg1);
batch.draw(background2, 0, yCoordBg2);
batch.end();
The background can be made in the format jpg - will spend less memory.
i have a java.util.List filled with java.io.File and i wan't to list them in a gui. To display them i wan't to show their name which is accessable by the method getName() of java.io.File. And i want to display their icon/image with which they are displayed for example on the desktop. To build this i am using the newest javaversion (Java8/1.8). So far i found one way to do get the image of any file which looks like this:
Icon icon = FileSystemView.getFileSystemView().getSystemIcon(pFile);
The problem about that is, that the returned icon is in a very small resolution(16x16) and i d like to display it in a bigger size. 80x80 would be perfect but doesn't have to be exactly it. 64x64 or smth like that would be fine, too. So i managed to resize the icon and stretch it but streatching 16x16 to 80x80 is not cool as you can imagine. There are to less pixels to get a good result.
I also found this tutorial but the first method shown in this tutorial doesn't work with Java8: http://www.rgagnon.com/javadetails/java-0439.html The method i am using right now is copied from there.
So is there any way to get a bigger sized icon like the one which is shown on the desktop of a specific file?
Thanks
Baschdi
private BufferedImage getBufferedImage(final File pFile)
throws FileNotFoundException {
Image icon = ShellFolder.getShellFolder(pFile).getIcon(true);
BufferedImage im = new BufferedImage(icon.getWidth(null),
icon.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = im.createGraphics();
g.drawImage(icon, 0, 0, null);
g.dispose();
int width = im.getWidth();
int height = im.getHeight();
System.out.println(width);
System.out.println(height);
final int maxHeigh = 79;
double scaleValue = 0;
if (height > width)
scaleValue = maxHeigh / height;
else
scaleValue = maxHeigh / width;
final int scaledWidth = (int) (im.getWidth() * scaleValue);
final int scaledHeigh = (int) (im.getHeight() * scaleValue);
BufferedImage resized = new BufferedImage(scaledWidth, scaledHeigh,
im.getType());
g = resized.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(im, 0, 0, scaledWidth, scaledHeigh, 0, 0, im.getWidth(),
im.getHeight(), null);
g.dispose();
return resized;
}
I imported the jdk7 and used the older function with ShellFolder. Works fine, even when running on java8. Thanks for the help :)
I have created a library called JIconExtractReloaded which can extract all icons sizes not only 32x32. Here is the link https://github.com/MrMarnic/JIconExtractReloaded.
Just write:
BufferedImage image = JIconExtract.getIconForFile(128,128,"C:\\Windows\\explorer.exe");
And you have the icon.
I need a bit logical help with my program. I need to crop a photo to be 600x600 around the point ( x, y ). The thing I need help with is when the point is close to the edge, how can I then move the cropped area so it fits inside the photo.
I have the code:
BufferedImage finalImg = capture.getSubimage(Math.max( 0, x - 300 ), Math.max( 0, y - 300 ), 200, 200 );
As far as I can see, the code works for the top and left side, but I have no clue how to get the same effect on the bottom and right side.
If it helps, I want to capture the screen and crop the photo around the mouse ( x, y ).
Thank you
BufferedImage originalImage = readImage(inputFileLocation);
/**
* Image Cropping Parameters
*/
int cropHeight = 600;
int cropWidth = 600;
int cropStartX = 50;
int cropStartY = 50;
BufferedImage processedImage = cropMyImage(originalImage, cropWidth,
cropHeight, cropStartX, cropStartY);
follow this site for full code.
I'm currently turning an array of pixel values (originally created with a java.awt.image.PixelGrabber object) into an Image object using the following code:
public Image getImageFromArray(int[] pixels, int width, int height) {
MemoryImageSource mis = new MemoryImageSource(width, height, pixels, 0, width);
Toolkit tk = Toolkit.getDefaultToolkit();
return tk.createImage(mis);
}
Is it possible to achieve the same result using classes from the ImageIO package(s) so I don't have to use the AWT Toolkit?
Toolkit.getDefaultToolkit() does not seem to be 100% reliable and will sometimes throw an AWTError, whereas the ImageIO classes should always be available, which is why I'm interested in changing my method.
You can create the image without using ImageIO. Just create a BufferedImage using an image type matching the contents of the pixel array.
public static Image getImageFromArray(int[] pixels, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
WritableRaster raster = (WritableRaster) image.getData();
raster.setPixels(0,0,width,height,pixels);
return image;
}
When working with the PixelGrabber, don't forget to extract the RGBA info from the pixel array before calling getImageFromArray. There's an example of this in the handlepixelmethod in the PixelGrabber javadoc. Once you do that, make sure the image type in the BufferedImage constructor to BufferedImage.TYPE_INT_ARGB.
Using the raster I got an ArrayIndexOutOfBoundsException even when I created the BufferedImage with TYPE_INT_ARGB. However, using the setRGB(...) method of BufferedImage worked for me.
JavaDoc on BufferedImage.getData() says: "a Raster that is a copy of the image data."
This code works for me but I doubt in it's efficiency:
// Получаем картинку из массива.
int[] pixels = new int[width*height];
// Рисуем диагональ.
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
if (i == j) {
pixels[j*width + i] = Color.RED.getRGB();
}
else {
pixels[j*width + i] = Color.BLUE.getRGB();
//pixels[j*width + i] = 0x00000000;
}
}
}
BufferedImage pixelImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
pixelImage.setRGB(0, 0, width, height, pixels, 0, width);
I've had good success using java.awt.Robot to grab a screen shot (or a segment of the screen), but to work with ImageIO, you'll need to store it in a BufferedImage instead of the memory image source. Then you can call one static method of ImageIO and save the file. Try something like:
// Capture whole screen
Rectangle region = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capturedImage = new Robot().createScreenCapture(region);
// Save as PNG
File imageFile = new File("capturedImage.png");
ImageIO.write(capturedImage, "png", imageFile);
As this is one of the highest voted question tagged with ImageIO on SO, I think there's still room for a better solution, even if the question is old. :-)
Have a look at the BufferedImageFactory.java class from my open source imageio project at GitHub.
With it, you can simply write:
BufferedImage image = new BufferedImageFactory(image).getBufferedImage();
The other good thing is that this approach, as a worst case, has about the same performance (time) as the PixelGrabber-based examples already in this thread. For most of the common cases (typically JPEG), it's about twice as fast. In any case, it uses less memory.
As a side bonus, the color model and pixel layout of the original image is kept, instead of translated to int ARGB with default color model. This might save additional memory.
(PS: The factory also supports subsampling, region-of-interest and progress listeners if anyone's interested. :-)
I had the same problem of everyone else trying to apply the correct answer of this question, my int array actually get an OutOfboundException where i fixed it adding one more index because the length of the array has to be widht*height*3 after this i could not get the image so i fixed it setting the raster to the image
public static Image getImageFromArray(int[] pixels, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
WritableRaster raster = (WritableRaster) image.getData();
raster.setPixels(0,0,width,height,pixels);
image.setData(raster);
return image;
}
And you can see the image if u show it on a label on a jframe like this
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(new JLabel(new ImageIcon(image)));
frame.pack();
frame.setVisible(true);
setting the image on the imageIcon().
Last advice you can try to change the Bufferedimage.TYPE_INT_ARGB to something else that matches the image you got the array from this type is very important i had an array of 0 and -1 so I used this type BufferedImage.TYPE_3BYTE_BGR