I have this png file and converted it to jpg image.
As you can see, some pixels around the circles are not as smooth as the circles in the png image.
I have this code to convert png to jpeg. How do I update the code so that I can remove the noise around the circles.
BufferedImage bufferedJpgImage = new BufferedImage(inputPngImage.getWidth(null),
inputPngImage.getHeight(null),
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage(inputPngImage, 0, 0, bufferedJpgImage.getWidth(), bufferedJpgImage.getHeight(), Color.WHITE, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bufferedJpgImage, "jpg", out);
Jpeg uses a lossy compression algorithm, this means that the physical image data is modified in order to reduce the image size.
You can set the compression level through ImageIO, it's a little messy, but it should provide you the control you need.
So based the answer from Setting jpg compression level with ImageIO in Java, you could do something like:
The left is the original BufferedImage and the right is the resulting JPEG
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
try {
BufferedImage original = ImageIO.read(...);
BufferedImage bufferedJpgImage = new BufferedImage(original.getWidth(null),
original.getHeight(null),
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedJpgImage.createGraphics();
g.drawImage(original, 0, 0, original.getWidth(), original.getHeight(), Color.WHITE, null);
g.dispose();
File jpg = new File("tmp.jpg");
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
write(bufferedJpgImage, baos);
try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) {
BufferedImage image = ImageIO.read(bais);
JPanel panel = new JPanel();
panel.add(new JLabel(new ImageIcon(original)));
panel.add(new JLabel(new ImageIcon(image)));
JOptionPane.showMessageDialog(null, panel);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void write(BufferedImage capture, OutputStream to) throws IOException {
// use IIORegistry to get the available services
IIORegistry registry = IIORegistry.getDefaultInstance();
// return an iterator for the available ImageWriterSpi for jpeg images
Iterator<ImageWriterSpi> services = registry.getServiceProviders(ImageWriterSpi.class,
new ServiceRegistry.Filter() {
#Override
public boolean filter(Object provider) {
if (!(provider instanceof ImageWriterSpi)) {
return false;
}
ImageWriterSpi writerSPI = (ImageWriterSpi) provider;
String[] formatNames = writerSPI.getFormatNames();
for (int i = 0; i < formatNames.length; i++) {
if (formatNames[i].equalsIgnoreCase("JPEG")) {
return true;
}
}
return false;
}
},
true);
//...assuming that servies.hasNext() == true, I get the first available service.
ImageWriterSpi writerSpi = services.next();
ImageWriter writer = writerSpi.createWriterInstance();
// specifies where the jpg image has to be written
writer.setOutput(ImageIO.createImageOutputStream(to));
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(1f);
// writes the file with given compression level
// from your JPEGImageWriteParam instance
writer.write(null, new IIOImage(capture, null, null), jpegParams);
}
}
You need to make sure you're managing your resources properly, closing or disposing of them when you have finished with them
What you are seeing is a natural consequence of JPEG compression in non-photographic images. JPEG relies on people not being able to notice small graduations in photographic images. When there is an abrupt change from one color to another, you get the artifacts you see.
You can reduce this effect by quantization table selection (quality settings in most encoders) and not sampling the Cb and Cr components at a lower rate than Y.
However, for an image like what you are showing, you are better off sticking with PNG.
Related
I have found that java awt can capture the full-screen, but how can I capture the screen of a specific applications? For example, I opened a matlab application and eclipse application. And I cannot tell the size of application screen to the program and just know the matlab is an active window now. And I want to only capture the screen of Matlab. How can I do that?
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.File;
import javax.imageio.ImageIO;
public class Screenshot {
public static final long serialVersionUID = 1L;
public static void main(String[] args)
{
try {
Thread.sleep(120);
Robot r = new Robot();
// It saves screenshot to desired path
String path = "D:// Shot.jpg";
// Used to get ScreenSize and capture image
Rectangle capture =
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage Image = r.createScreenCapture(capture);
ImageIO.write(Image, "jpg", new File(path));
System.out.println("Screenshot saved");
}
catch (AWTException | IOException | InterruptedException ex) {
System.out.println(ex);
}
}
}
To capture screenshot of a portion of the screen, we need to specify a rectangle region to be captured.the following statements create a capture region which is the first quarter of the screen.
try {
Robot robot = new Robot();
String format = "jpg";
String fileName = "PartialScreenshot." + format;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle captureRect = new Rectangle(0, 0, screenSize.width / 2, screenSize.height / 2);
BufferedImage screenFullImage = robot.createScreenCapture(captureRect);
ImageIO.write(screenFullImage, format, new File(fileName));
System.out.println("A partial screenshot saved!");
} catch (AWTException | IOException ex) {
System.err.println(ex);
}
like this blank image is saving
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.effect.Light.Point;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
public class JavaFxSelectPlay extends Application {
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
WebView wv = new WebView();
WebEngine Img = wv.getEngine();
Img.load("https://app.leadlock.pro/upload/69/1019/images/welcome.jpeg");
final Rectangle selection = new Rectangle();
final Point anchor = new Point();
wv.setOnMousePressed(event -> {
anchor.setX(event.getX());
anchor.setY(event.getY());
selection.setX(event.getX());
selection.setY(event.getY());
selection.setFill(null); // transparent
selection.setStroke(Color.BLACK); // border
selection.getStrokeDashArray().add(10.0);
root.getChildren().add(selection);
});
wv.setOnMouseDragged(event -> {
selection.setWidth(Math.abs(event.getX() - anchor.getX()));
selection.setHeight(Math.abs(event.getY() - anchor.getY()));
selection.setX(Math.min(anchor.getX(), event.getX()));
selection.setY(Math.min(anchor.getY(), event.getY()));
});
wv.setOnMouseReleased(event -> {
// Do what you want with selection's properties here
System.out.printf("X: %.2f, Y: %.2f, Width: %.2f, Height: %.2f%n",
selection.getX(), selection.getY(), selection.getWidth(), selection.getHeight());
// root.getChildren().remove(selection);
// selection.setWidth(0);
// selection.setHeight(0);
});
wv.addEventFilter(KeyEvent.KEY_RELEASED, (KeyEvent e1) -> {
if (e1.getCode() == KeyCode.SPACE ) {
selection.setFill(Color.WHITE); // transparent
}
});
wv.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(final KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.F5) {
System.out.println("F5 pressed");
//Stop letting it do anything else
// WritableImage croppedImage = selection.snapshot(null, null);
WritableImage image = selection.snapshot(new SnapshotParameters(), null);
// TODO: probably use a file chooser here
File file = new File("C:/temp/snapshot.jpg");
try {
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "jpg", file);
} catch (IOException e) {
// TODO: handle exception here
}
}
System.out.println("snapshot saved: " );
}
});
root.getChildren().add(wv);
Scene scene = new Scene(root, 300, 200);
primaryStage.setScene(scene);
primaryStage.setTitle("Primary Stage");
primaryStage.show();
}
}
this code i tried and its running fine but the image that is saved is saved with white color its not saved the orginal selected image so how can i do it please help i need to save the selected image and i had done white but not with white color but the selected image so please tell me how to do it and what im doing wrong.
It seems there are two things going on here.
Firstly, instead of taking a snapshot of the Rectangle you are using to mark the selection, you probably want to take a snapshot of the root and use the selection rectangle to specify what part of the snapshot to take. So, instead of writing
WritableImage image = selection.snapshot(new SnapshotParameters(), null);
try writing
SnapshotParameters params = new SnapshotParameters();
params.setViewport(
new Rectangle2D(
selection.getX(),
selection.getY(),
selection.getWidth(),
selection.getHeight()));
root.getChildren().remove(selection);
WritableImage image = root.snapshot(params, null);
I've also removed the rectangle from the root so that it doesn't appear in the output image.
The second thing that happens is that the image comes out pink. This appears to be an existing issue which is supposed to have been fixed in Java 8 but I can still reproduce it in Java 8 update 152. Adapting the code in the question I linked to, you would have to replace the line
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "jpg", file);
with
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null);
BufferedImage imageRGB = new BufferedImage(
bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.OPAQUE);
Graphics2D graphics = imageRGB.createGraphics();
graphics.drawImage(bufferedImage, 0, 0, null);
ImageIO.write(imageRGB, "jpg", file);
here's the problem: I have several images and would like to use them when displaying a HTML in JavaFX's WebView.
Current implementation is very obvious: there is a file, which is linked to in the HTML content. I assume that WebView does not regress from JEditorPane and will only do a single I/O operation even if the image is referenced 10 000 times throughout the content.
However, it would be great to have a single Image instance and feed it to WebView when it encounters the relevant <img> tag.
I have seen that there is a great half-solution involving URL handling, but the problem remains: you have an Image instance that you convert to a storage format (BMP, PNG with proprietary extensions, etc) and keep that in memory. However, this means that each time WebView desires an image resolution, it must then manually parse the image from binary data. In the end, you just have a file mapped to memory plus an internal Image instance instead of a shared Image instance.
With JEditorPane, you could push Images to its image cache and get rid of such problems. Unfortunately, since Java 7, that component is unusable and is out of question.
Basically, is there any chance WebView/WebEngine maintains such a cache/equivalent and is there a way to pre-populate it?
/**
* Encodes the image as a whole into PNG, then into Base64 and finally into an URI suitable for the HTML {#code <img>} tag.
*
* #param image an image
* #return image as URI (image within the URI)
* #throws IIOException if there is a fault with an image writer
* #throws IOException in case of a general I/O error
*/
public static final String getImageSrcForWebEngine(RenderedImage image) throws IIOException, IOException
{
final ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", output);
return "data:base64," + Base64.getMimeEncoder().encodeToString(output.toByteArray());
}
Example of usage:
RenderedImage image = […];
String tag = "<img src=\"" + getImageSrcForWebEngine(image) + "\" border=\"0\" />";
SSCCE:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewWithMemoryImages extends Application
{
private static String IMAGE_IN_MEMORY;
#Override
public void start(Stage primaryStage)
{
WebView webView = new WebView();
webView.getEngine().loadContent("<html><body><img src=\"" + IMAGE_IN_MEMORY + "\"></body></html>");
primaryStage.setScene(new Scene(webView, 420, 420));
primaryStage.show();
}
public static void main(String[] args) throws Exception
{
BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_BGR);
Graphics2D g = image.createGraphics();
try
{
g.setColor(Color.RED);
g.fillRect(0, 0, 400, 400);
g.setColor(Color.WHITE);
g.fillRect(50, 50, 300, 300);
g.setColor(Color.BLACK);
g.fillRect(100, 100, 200, 200);
g.drawString("No image files were used in this WebView.", 90, 70);
}
finally
{
g.dispose();
}
IMAGE_IN_MEMORY = getImageSrcForWebEngine(image);
launch(args);
}
public static String getImageSrcForWebEngine(RenderedImage image) throws IIOException, IOException
{
final ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", output);
return "data:base64," + Base64.getMimeEncoder().encodeToString(output.toByteArray());
}
}
I have a java swing project I have been working on that involves parsing text data and then displaying graphical representations through local image files. I want the user to be able to copy the images displayed so that they can be pasted into other programs (such as Microsoft Word). It doesn't even need to happen like that, just any way I can make .jpg files copied so the user can paste them elsewhere. There would be a long chain of images, so just copying and pasting one at a time is not a possibility. Please help!
So, I threw this together really quickly and it works just fine for me.
Basically, you should be able to "export" just about any java.awt.Image based image, including BufferedImage
Updated, now with improved stiching...
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageTransfer {
public static void main(String[] args) {
try {
BufferedImage left = ImageIO.read(new File("left"));
BufferedImage right = ImageIO.read(new File("right"));
BufferedImage img = new BufferedImage(
left.getWidth() + right.getWidth(),
Math.max(left.getHeight(), right.getHeight()),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(left, 0, (img.getHeight() - left.getHeight()) / 2, null);
g2d.drawImage(right, left.getWidth(), (img.getHeight() - right.getHeight()) / 2, null);
g2d.dispose();
final Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.setContents(new ImageTransferable(img), new ClipboardOwner() {
#Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
System.out.println("You Lose");
}
});
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static class ImageTransferable implements Transferable {
private BufferedImage img;
public ImageTransferable(BufferedImage img) {
this.img = img;
}
#Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.imageFlavor};
}
#Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return DataFlavor.imageFlavor.equals(flavor);
}
#Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (!isDataFlavorSupported(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
return img;
}
}
}
Note, while I loaded the image from a file, the image could be created dynamically in memory as well and it should work just fine...
Take a look at Writing/Saving an Image, Reading/Loading an Image and Drag and Drop and Data Transfer for more details
I need to get the background image from a PowerPoint slide using java. I am aware of the Apache POI project. I can find material for getting text and shapes from the slides, but not the actual background. Does anyone have any suggestions?
EDIT: I have creaked the following code using the suggested link. This code seems to grab the contents of the slide, but not exactly the background. The resulting images are white for the background.
I tried it with this PowerPoint
package PowerPointProcessing;
import Logging.LogRunner;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hslf.model.Background;
import org.apache.poi.hslf.model.Fill;
import org.apache.poi.hslf.model.Shape;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.usermodel.SlideShow;
/**
*
* #author dvargo
*/
public class PPI
{
Dimension pageSize;
public Slide[] theSlides;
public PPI(String powerPointFilePath)
{
SlideShow ppt = null;
//open the presentation
try
{
ppt = new SlideShow(new HSLFSlideShow(powerPointFilePath));
}
catch(Exception e)
{
LogRunner.getLogger().severe("Could not open the powerpoint presentation");
return;
}
//get all the slides
theSlides = ppt.getSlides();
//see how many slides there are
int numberOfSlides = theSlides.length;
pageSize = ppt.getPageSize();
}
public BufferedImage getBackground(Slide theSlide)
{
Background background;
background = theSlide.getBackground();
Fill f = background.getFill();
Color color = f.getForegroundColor();
Shape[] theShapes = theSlide.getShapes();
BufferedImage img = new BufferedImage(pageSize.width, pageSize.height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setPaint(color);
graphics.fill(new Rectangle2D.Float(0, 0, pageSize.width, pageSize.height));
theSlide.draw(graphics);
return img;
}
public static void main(String[] args) {
PPI ppi = new PPI("C:\\Documents and Settings\\dvargo\\Desktop\\Cludder\\a.ppt");
int count= 0;
for (Slide currSlide : ppi.theSlides)
{
BufferedImage img = ppi.getBackground(currSlide);
try
{
ImageIO.write(img, "jpeg", new File("C:\\Documents and Settings\\dvargo\\Desktop\\ppt\\" + count + ".jpeg"));
}
catch (IOException ex)
{
Logger.getLogger(PPI.class.getName()).log(Level.SEVERE, null, ex);
}
count++;
}
}
}
Looking at the code from this question:
Extracting images from pptx with apache poi
Looks like it should be something like:
Background background = slides[current].getBackground();
Fill f = background.getFill();
Color color = f.getForegroundColor();