I'm trying to capture a specific part of my screen and save it as a JPG image.
This is what I've tried thus far:
Robot r = new Robot();
// It saves screenshot to desired path
String path = "Health_Bar.JPG";
// Used to get ScreenSize and capture image
//Dimension dim = new Dimension(376, 54, 58, 18);
Rectangle capture =
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage Image = r.createScreenCapture( new Rectangle(191, 229, 473, 150) );//r.createScreenCapture(capture);
ImageIO.write(Image, "jpg", new File(path));
System.out.println("Screenshot saved");
This code is not working as expected. I expect the x and y coordinate to be the top left corner coordinate of the image captured. And even though this is true in some cases i.e. if x,y=0; it is not in most other cases i.e x=191, y=229, as in the example code above.
For the example code above this is the out I get output image from code. However this is the image I expect to get Image of expected output. The coordinates in image 2 (expected output image) is the coordinate for the top left corner of the "Mofiki's Coordinate Finder" window.
Can anyone explain whats going on and how to fix it?
Related
everybody. I'm trying to place ".png" image over the video capture using java and opencv.
I performed the tutorial from the official opencv java website http://opencv-java-tutorials.readthedocs.io/en/latest/04-opencv-basics.html
In this tutorial everything works fine with png image from the tutorial. But when i try to load my own png image with alpha channel, i get the wrong result. Png image displays with white spaces.
Here is the print screens of video capture with both images:
correct output
incorrect output
my png image
Here is the code of loading image:
#FXML
protected void loadLogo() {
if(logoCheckBox.isSelected()) {
this.logo = Imgcodecs.imread("resources/Poli.png", Imgcodecs.IMREAD_COLOR);
}
}
Here is the code of video capture and placing png image over it:
Mat frame = new Mat();
// read the current frame
this.capture.read(frame);
Rect roi = new Rect(frame.cols() - logo.cols(), frame.rows() - logo.rows(), logo.cols(), logo.rows());
Mat imageROI = frame.submat(roi);
Core.addWeighted(imageROI, 1.0, logo, 1.0f, 0.0, imageROI);
And here is how output image place inside ImageView:
MatOfByte buffer = new MatOfByte();
Imgcodecs.imencode(".png", frame, buffer);
Image imageToShow = new Image(new ByteArrayInputStream(buffer.toArray()));
Image imageToShow = Utils.mat2Image(frame);
currentFrame.setImage(imageToShow);
I know that parameter Imgcodecs.IMREAD_COLOR load image with 3 channels, without alpha, but when i change this parameter to IMREAD_UNCHANGED i got this error:
OpenCV Error: Sizes of input arguments do not match (The operation is neither 'array op array' (where arrays have the same size and the same number of channels)
This is appear becouse the input Mat with video capture contains only 3 channels.
My question is: how can i load and place png image over video capture correctly ?
P.S When i fill the background of png image with black, its displayd correct, but image is still stay transparent.
The answer is that RGBA image cannot be placed over RGB video capture. Placing only RBG components of png image gives "wrong result".
For now, the best solution i found is to load png image in RBGA mode COLOR_UNCHANCHED wiht 4 channels, take the 4-th alpha channel and use it as mask for displaying image with function "copyTo" instead of "addWeighted".
But this method doesnt work with translucent parts of PNG image like shadows, and objects with low opacity.
Here is the code of loading image with separate RGB and alpha channel:
Mat logo = new Mat();
Mat logo_alpha = new Mat();
Mat logo_with_alpha = Imgcodecs.imread("resources/TREE_1.png", Imgcodecs.IMREAD_UNCHANGED);
Vector<Mat> rgba = new Vector<Mat>();
// split RBGA image for separate channels
Core.split(logo_with_alpha, rgba);
// get alpha channel
logo_alpha = rgba.get(3);
// remove alpha channel to get RGB image
rgba.remove(rgba.size()-1);
// get image with only RGB components
Core.merge(rgba, this.logo);
Here is the code of video capturing and placing png image over it:
Mat frame = new Mat();
// read the current frame
this.capture.read(frame);
Rect roi = new Rect(frame.cols() - logo.cols(), frame.rows() - logo.rows(), logo.cols(), logo.rows());
Mat imageROI = frame.submat(roi);
// place logo with alpha on the frame
logo.copyTo(imageROI, logo_alpha);
i need to write a program which takes an image, resizes and rotates it and then saves it out. The first 2 point are done, but now I have a problem. Every time I convert a grayscale image it becomes a monochrome image.
I load the target image with the following command:
BufferedImage sourceimg = ImageIO.read(input);
And after I scaled and rotated it I save it out with the following command:
BufferedImage newimg = new BufferedImage(sourceimg.getHeight(), sourceimg.getWidth(), sourceimg.getType());
op.filter(sourceimg, newimg);
sourceimg = newimg;
ImageIO.write(sourceimg, "png", outputFile);
This works fine for every image except grayscale images. I have already tried a workaround by setting the type of every image to ARGB but there has to be another way. Is there a way to get the IndexColorModel of an given image?
The problem ist now solved, i just had to change:
BufferedImage newimg = new BufferedImage(sourceimg.getHeight(), sourceimg.getWidth(), sourceimg.getType());
to:
BufferedImage newimg = new BufferedImage(sourceimg.getWidth(), sourceimg.getHeight(), BufferedImage.TYPE_INT_ARGB);
There are other solutions, especially if you like to keep the original image type (ie. keep palette of IndexColorModel images etc.).
In fact, the easiest is to just do (assuming op is a standard BufferedImageOp):
BufferedImage newimg = op.filter(sourceimg, null);
Here a new, compatible image will be created for you, and will be of correct size to keep the result of the operation.
Another option, which will preserve the image type and color model, is slightly more verbose:
ColorModel sourceCM = sourceimg.getColorModel(); // Will be the IndexColorModel in your case
// I'm assuming you are deliberately switching width/height to rotate 90 deg
WritableRaster raster = sourceCM.createCompatibleWritableRaster(sourceimg.getHeight(), sourceimg.getWidth());
BufferedImage newimg = new BufferedImage(sourceCM, raster, sourceCM.isAlphaPremultiplied(), null);
op.filter(sourceimg, newimg);
This question already has an answer here:
Swing: Obtain Image of JFrame
(1 answer)
Closed 7 years ago.
Heys guys, I've developped a code to take a screen shot of my whole screen, but I want it to take the screen shot of only the things inside my Jframe. Ill be using it to print the image later on by the way. And one of the main problem is, the mouse also comes inside the snapshot. I don't want the mouse or the two buttons at the bottom. I can just change visi of buttons but what should be done for mouse and inside Jframe only shot? Here is my code it takes screen shot of whole screen.
try{
Thread.sleep(1000);
Toolkit tk = Toolkit.getDefaultToolkit(); //Toolkit class returns the default toolkit
Dimension d = tk.getScreenSize();
//Dimension class object stores width & height of the toolkit screen
// toolkit.getScreenSize() determines the size of the screen
Rectangle rec = new Rectangle(0, 0, d.width, d.height);
//Creates a Rectangle with screen dimensions,
Robot ro = new Robot(); //to capture the screen image
BufferedImage img = ro.createScreenCapture(rec);
File f;
f = new File("myimage.jpg"); // File class is used to write the above generated buffered image to a file
ImageIO.write(img, "jpg", f);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
IMHO it is better to make an image of your component (a JFrame is also a Component):
BufferedImage img = new BufferedImage(yourComponent.getWidth(), yourComponent.getHeight(), BufferedImage.TYPE_INT_RGB);
yourComponent.paint(img.getGraphics());
File outputfile = new File("saved.png");
ImageIO.write(img, "png", outputfile);
I'm trying to rotate an image using thumbnailator library. It works fine except I don't see any way to set background color of the new image.
Thumbnails.of(image).rotate(45).toByteArray()
If I rotate an image 45 degree it makes corners black. If I need to set some other color, how do I do this?
Example of a rotated image with black background:
You can transform to an "intermediate" image and then apply your background color.
This is mostly untested.
Color newBackgroundColor = java.awt.Color.WHITE;
// apply your transformation, save as new BufferedImage
BufferedImage transImage = Thumbnails.of(image)
.size(100, 60)
.rotate(45)
.outputQuality(0.8D)
.outputFormat("jpeg")
.asBufferedImage();
// Converts image to plain RGB format
BufferedImage newCompleteImage = new BufferedImage(transImage.getWidth(), transImage.getHeight(),
BufferedImage.TYPE_INT_ARGB);
newCompleteImage.createGraphics().drawImage(transImage, 0, 0, newBackgroundColor, null);
// write the transformed image with the desired background color
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(newCompleteImage, "jpeg", baos);
http://www.robinswebsitestudio.com/ButtonSamples/buttons.html
The following code does write to a premade image. The resulting image, though, has significant problems.
the original png file is a 3D button with Index Transparency and a matte so that the gif file would
blend in with the page background color
the resulting gif file is flat, the matte is gone, and the text doesn’t look smooth. The resulting
file is therefore is not something you would get from Adobe Photoshop or Fireworks and doesn’t look
professional.
If anyone has suggestions, I’m all ears. Is it impossible to get a high quality 3D button using Java?
String pathToWeb = getServletContext().getRealPath(File.separator);
File f = new File(pathToWeb + "activities.png");
BufferedImage bufferedImage = ImageIO.read(f);
// Create a graphics which can be used to draw into the buffered image
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setFont(new Font( "Arial", Font.BOLD, 15 ));
//create a string with black
g2d.setColor(Color.black);
g2d.drawString("Activities", 40, 40);
// Disposes of this graphics context and releases any system resources that it is using.
g2d.dispose();
// Save as gif
File file = new File("myactivities.gif");
ImageIO.write(bufferedImage, "gif", file);