Changing image quality - java

I'm trying to create remote control application in Java. I'm using robot to capture my screen image, and then I need to send it to the server. However, because the image size may be too big for the sending to be quick as possible, I'm changing the image quality in the code.
The problem is with the code I have, after changing the image it automatically save it as file in my computer but I don't want it to. I want it to the change it without saving it to be able to send it to my server
The code:
Robot robot = null;
Rectangle rectangle = null;
GraphicsEnvironment gEnv=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gDev=gEnv.getDefaultScreenDevice();
//Get screen dimensions
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
rectangle = new Rectangle(dim);
System.out.println(rectangle);
robot = new Robot(gDev);
BufferedImage image = robot.createScreenCapture(rectangle);
// FileInputStream inputStream = new FileInputStream(MyFile);
// BufferedImage originalImage = ImageIO.read(inputStream);
Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter)iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
float quality = 0.25f; // reduce quality by 50%
iwp.setCompressionQuality(quality);
File file = new File("Tester6.png");
FileImageOutputStream output = new FileImageOutputStream(file);
writer.setOutput(output);
IIOImage image1 = new IIOImage(image, null, null);
writer.write(null, image1, iwp);
writer.dispose();

Instead of creating a file, do:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
writer.setOutput(ios);
You can then use baos.toByteArray() to get the bytes after you have called writer.write().

Related

Retrieve multiple images from a bytearray in Java

I am working with a bytearray which contains multiple images. How can I retrieve the images from the bytearray in Java.
PDDocument document = null;
int pageCounter = 0;
BufferedImage bim = null;
document = PDDocument.load(pdfBytes);
PDFRenderer pdfRenderer = new PDFRenderer(document);
bim = pdfRenderer.renderImageWithDPI(pageCounter, 300, ImageType.RGB);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(rotate(bim), imageFormat, bos);
output = bos.toByteArray();
rotate is a method to rotate the image. I want to rotate only one Image. The other I do not want to rotate. Also I want to output it again in Bytes

Write GeoTIFF metadata from one file to other

My task is to take one GeoTIFF, make some image segmentation on in, and save it to new GeoTIFF(with existing coordinates). If I understand correctly, the coordinates are preserved in GeoTIFF metadata.
So I grab metadata from the original file:
File file = new File(inputFilePath);
ImageInputStream iis = ImageIO.createImageInputStream(file);
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
IIOMetadata metadata=null;
ImageReader reader=null;
if (readers.hasNext()) {
// pick the first available ImageReader
reader = readers.next();
// attach source to the reader
reader.setInput(iis, true);
// read metadata of first image
metadata = reader.getImageMetadata(0);
}
And when I do
System.out.println("Metadata: "+metadata);, I see the correct XML tree of metatags.
So I'm do some magic with image
System.out.println("Starting segmentation");
BufferedImage image = UtilImageIO.loadImage(inputImage);
// Select input image type. Some algorithms behave different depending on image type
ImageType<MultiSpectral<ImageFloat32>> imageType = ImageType.ms(3, ImageFloat32.class);
ImageSuperpixels alg = FactoryImageSegmentation.fh04(new ConfigFh04(500, 30), imageType);
// Convert image into BoofCV format
ImageBase color = imageType.createImage(image.getWidth(), image.getHeight());
ConvertBufferedImage.convertFrom(image, color, true);
// Segment and display results
performSegmentation(alg, color);
System.out.println("Segmentation finished");
In result I obtain a BufferedImage(resultBufferedImage) with successfully image segmentation.
And here starts my problems, I'm trying to save this BufferedImage with old metadata:
BufferedOutputStream out;
ImageWriter writer = ImageIO.getImageWriter(reader);
ImageOutputStream imgout = null;
FileOutputStream fos =null;
fos = new FileOutputStream(outputImage);
out = new BufferedOutputStream(fos);
imgout = ImageIO.createImageOutputStream(out);
writer.setOutput(imgout);
ImageWriteParam param = writer.getDefaultWriteParam();
IIOImage destIIOImage = new IIOImage(resultBufferedImage, null, metadata);
System.out.println("Before write");
writer.write(null, destIIOImage, null);
System.out.println("After write");
I get printed "After write". But program is still running, I tried to wait, but no results. So when I kill process the file is created successfully, even with geodata. How can I determine the finish of writing and stop program?
p.s. Image in default Ubuntu viewer seems to be nice, but when I opened it in QGIS I have transparent fields, and how can I make gray background transparent?
Not a real answer, but here's two answers on how to make a TIFF transparent:
QGis problem with raster transparent
How to make transparent the background of a topographic map in QGis 1.8.0?

antialiasing in java image scaling library

I am currently using http://code.google.com/p/java-image-scaling/ this library to generate scaled images for my web app.But when I scale down the image to about 100x100 size there are some leftover artifacts visible in some images. Is this an issue with antialiasing? And how do I use antialiasing with this library.The api documentation doesn't say any thing about it.
Here is the code
File f = new File("C:\\Users\\ad min\\Pictures\\30-whisky-3d-wallpaper-1152x864.jpg");
BufferedImage src = ImageIO.read(f);
//ResampleOp resampleOp = new ResampleOp(76, 76);
ResampleOp resampleOp = new ResampleOp(200,200);
resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.VerySharp);
BufferedImage rescaled = resampleOp.filter(src, null);
ImageIO.write(rescaled, "JPG", new File(
"C:\\Users\\ad min\\Pictures\\scaleddown.jpg"));
what am I doing wrong?
I finally didn't need antialiasing I simply used this code given in the foloowing link and it worked :) whewww
http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-
compression-quality-when-saving-images-in-java
Iterator<ImageWriter> iter = ImageIO
.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter) iter.next();
// instantiate an ImageWriteParam object with default compression
// options
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(1); // an integer between 0 and 1
// 1 specifies minimum compression and maximum quality
File file = new File("C:\\Users\\ad min\\Pictures\\scaleddown.jpg");
FileImageOutputStream output = new FileImageOutputStream(file);
writer.setOutput(output);
IIOImage image = new IIOImage(rescaled, null, null);
writer.write(null, image, iwp);
writer.dispose();

Reduce JPEG image size without scale its width/height by Java

I want to reduce one jpeg image size(3M reduce to 1M) by Java, without scale(no change for image height and width). IN this site, I could not find a solution. Below is what I have tried:
1 Using ImageIO:
BufferedImage image = ImageIO.read(inputFile);
ImageWriter writer = null;
Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
if(iter.hasNext()){
writer = (ImageWriter) iter.next();
}
ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile);
writer.setOutput(ios);
ImageWriteParam iwParam = writer.getDefaultWriteParam();
iwParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwParam.setCompressionQuality(compressionQuality);
writer.write(null, new IIOImage(image, null, null ), iwParam);
For solution 1, I set compressionQuality for jpg but I can not obtain origina image compressQuality and the newImage I get sometimes is bigger than originals.
The compression quality used is not stored with the JPEG image.
If you need to get below a certain threshold you must try several times while lowering the compression quality each time until you reach your limit. Be aware that very low settings give bad images.
I am unfamiliar with the MODE_EXPLICIT flag. It might also be a tunable parameter.
I found the following code example for reducing the quality.
The important part is just to set iwp.setCompressionQuality. Hopes this helps.
BufferedImage bi = null;
bi = ImageIO.read(new File("image.jpg"));
Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter) iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// reduced quality.
iwp.setCompressionQuality(0.1f);
File file = new File("c:/image_low.jpg");
FileImageOutputStream output = null;
output = new FileImageOutputStream(file);
writer.setOutput(output);
IIOImage image = new IIOImage(bi, null, null);
writer.write(null, image, iwp);
writer.dispose();

How to select a portion of an image and save just that portion to a file

I am taking a screenshot of the current screen then saving the image. I want to open that image up and be able to select a box of a certain element or whatever it is i want the pic to be of and to be able to in turn save that smaller selected image to
a file. Please help.
RemoteControlConfiguration config = new RemoteControlConfiguration();
config.setPort(4447);
SeleniumServer server = new SeleniumServer(config);
try{
// TODO Auto-generated method stub
server.start();
DefaultSelenium selenium = new DefaultSelenium("localhost", 4447, "*firefox", "http://www.google.com/");
selenium.start();
selenium.open("http://www.google.com/");
selenium.waitForPageToLoad("10000");
selenium.windowMaximize();
BufferedImage image1 = Screenshot("screen1.jpg");
//selenium.type("q", "Hello world");
Thread.sleep(2000);
BufferedImage image2 = Screenshot("screen2.jpg");
public static BufferedImage Screenshot(String fileName) throws Exception
{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRectangle = new Rectangle(screenSize);
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(screenRectangle);
File file = new File(fileName);
ImageIO.write(image, "jpg", file);
return image;
}
Assuming you know the coordinates of your new bounds, create a new BufferedImage with the new size, create a graphics object for your new image, and paint the big image on this graphics object, specifying negative values for the x,y. The source image is bigger than the destination, so only the bits that fit within the destination will be written. Then you save out the smaller one using ImageIO.write()
EDIT
Thanks to Andrew Thompson for the suggestion to use subImage
BufferedImage image1 = Screenshot("screen1.jpg");
BufferedImage subImage = image1.getSubImage(x, y, width, height);

Categories