Retrieve Image in different Size from Database - java

I have stored some images in database, while retrieving them i want to resize it to 177x122. How can i do that in JAVA?
Here is some code that i have used to retrieve image from database, what changes need to be done to get a image of 177x122.
PreparedStatement pstm1 = con.prepareStatement("select * from image");
ResultSet rs1 = pstm1.executeQuery();
while(rs1.next()) {
InputStream fis1;
FileOutputStream fos;
String image_id;
try {
fis1 = rs1.getBinaryStream("image");
image_id=rs1.getString("image_id");
fos = new FileOutputStream(new File("images" + (image_id) + ".jpg"));
int c;
while ((c = fis1.read()) != -1) {
fos.write(c);
}
fis1.close();
fos.close();
JOptionPane.showMessageDialog(null, "Image Successfully Retrieved");
} catch (Exception ex) {
System.out.println(ex);
}
}

You can use the AWT provided BufferedImage and Graphics2D classes to resize your images. Source
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();

Assuming the data in the image column is a image format that the Java Image I/O can read (such as JPEG and PNG), the Thumbnailator library should be able to achieve this.
The code which would retrieve the image data from the ResultSet as an InputStream and write to specified file can be written like this:
// Get the information we need from the database.
String imageId = rs1.getString("image_id");
InputStream is = rs1.getBinaryStream("image");
// Perform the thumbnail generation.
// You may want to substitute variables for the hard-coded 177 and 122.
Thumbnails.of(is)
.size(177, 122)
.toFile("images" + (imageId) + ".jpg");
// Thumbnailator does not automatically close InputStreams
// (which is actually a good thing!), so we'll have to close it.
is.close();
(I should disclaim that I haven't actually run this code against an actual database.)
Thumbnailator will read the image data from the InputStream retrieving binary data from the image column, then resize the image to fit into the 172 x 122 region, and finally output the thumbnail as a JPEG to the specified file.
By default, Thumbnailator will preserve the aspect ratio of the original image when resizing images (to prevent the thumbnail from looking distorted), so the image size will not necessarily be 172 x 122. If this behavior is undesirable, calling the forceSize method instead of the size method can achieve that.
Disclaimer: I maintain the Thumbnailator library.

Related

How can I get the actual color of the image while uploading to Bugzilla tool using java code with out any distortion?

**I'm using the below code to fetch the multiple failure screenshots from the folder to Bugzilla tool, while uploading the pictures in bugzilla, color of the picture is disorted. [enter image description here][1]. Can any one help me to rectify this issue. ? **
try {
BugzillaConnector conn = new BugzillaConnector();
conn.connectTo("bugzilla.com");
LogIn logIn = new LogIn("username", "password");
conn.executeMethod(logIn);
Bug bug = new BugFactory()
.newBug()
.setProduct("SeleniumFramework")
.setComponent("CoreJavaTestNG")
.setVersion("1.0").setPlatform("PC")
.setOperatingSystem("Windows")
.setDescription("Bug posted from Java Source Code")
.setSummary("Bug posted from Java Source Code")
.createBug();
ReportBug report = new ReportBug(bug);
conn.executeMethod(report);
int bugID = report.getID();
System.out.println("Bug posted and its ID is " + bugID);
GetBug get = new GetBug(bugID);
conn.executeMethod(get);
System.out.println(get.getBug().getID());
System.out.println(get.getBug().getSummary());
System.out.println(get.getBug().getProduct());
System.out.println(get.getBug().getComponent());
System.out.println(get.getBug().getVersion());
System.out.println(get.getBug().getPlatform());
System.out.println(get.getBug().getOperatingSystem());
// Passing txtFileFilter to listFiles() method to retrieve only file start with fail files
File[] files = folder.listFiles(txtFileFilter);
int Count = 0;
for (File file : files) {
BufferedImage bImage = ImageIO.read(new File(FilePath + file.getName()));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(bImage, "jpg", bos );
byte [] data = bos.toByteArray();
AttachmentFactory attachmentFactory = new AttachmentFactory();
Attachment attachment = attachmentFactory.newAttachment()
. setData(data)
. setMime("image/jpg") //Set the appropriate MIME type for the image format
. setSummary(file.toString()) //Description
. setName(file.toString())//Name of the Screenshot in Bugzilla
. setBugID(bugID)
. createAttachment();
AddAttachment add2 = new AddAttachment(attachment, bugID);
add2.getID();
conn.executeMethod(add2);
Count++;
}
System.out.println(Count + " File Uploded");
}
catch (Exception e) {
e.printStackTrace();
} ```
[1]: https://i.stack.imgur.com/qrIaq.jpg
The pinkish/readish ting your seeing is because the source image contains a alpha channel.
There is a known bug in ImageIO which will include the alpha channel into the output of the JPEG image (or some such thing, you can google it if you're really interested).
The basic solution to your problem is to apply the original image to a BufferedImage using a TYPE_INT_RGB, which will remove the alpha channel, for example see Removing transparency in PNG BufferedImage.
I used the code but am getting blue color background on the image
So, starting with this transparent PNG
And using the below code...
BufferedImage original = ImageIO.read(new File("/Users/shanew/Downloads/transparent.png"));
BufferedImage copy = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = copy.createGraphics();
g2d.setColor(Color.WHITE); // Or what ever fill color you want...
g2d.fillRect(0, 0, copy.getWidth(), copy.getHeight());
g2d.drawImage(original, 0, 0, null);
g2d.dispose();
File dest = new File("Test.jpg");
ImageIO.write(copy, "jpg", dest);
BufferedImage test = ImageIO.read(dest);
JPanel panel = new JPanel();
panel.add(new JLabel(new ImageIcon(original)));
panel.add(new JLabel(new ImageIcon(test)));
JOptionPane.showMessageDialog(null, panel);
I can produce...
If you're still having issues, then you need to do two things:
Update your original question with the code you are using
Provide a sample of the image you are trying to convert
It's not helpful to keep posting code in the comments

How to set PIxelFormat to rgb in javafx?

With javafx, when I read images the PixelFormat is rgb and I want to apply filters on them.I use writableImage.pixelWriter to set the pixels color but the PixelFormat is rgba.
I use ImageIO.write() and it work for .png, but when I try to save this modified image in .jpg or .jpeg, the color change. I find that's because rgba don't work with jpg but i don't know how to change this PixelFormat.
Is there a way to change rgba format in rgb ? Do you know another way to save javafx Image as .jpg/.jpeg ?
Edit : How I save file (it works for png)
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("JPG Files", "*.jpg"));
File outputFile = fileChooser.showSaveDialog(null);
BufferedImage bImage = SwingFXUtils.fromFXImage(modifiedImage.getImage(), null); // getImage() return a javafx.scene.image.Image;
try {
ImageIO.write(bImage, "jpg", outputFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
How I modify image (example)
Image currentImage = modifiedImage.getImage();
WritableImage writableImage = new WritableImage((int) currentImage.getWidth(), (int) currentImage.getHeight());
PixelReader pixelReader = currentImage.getPixelReader();
PixelWriter pixelWriter = writableImage.getPixelWriter();
for (int i = 0; i < (int) currentImage.getWidth(); i++) {
for (int j = 0; j < (int) currentImage.getHeight(); j++) {
pixelWriter.setColor(i, j, new Color(0,0,0,1));
}
}
modifiedImage.setImage(writableImage);
When I get the PixelFormat of the reader it's rgb but for the writer it's rgba. If I save an image without modification it's good, but when I apply a filter on it and I save the image as jpg, the colors change.
On my app the colors are good but if I open the jpg file outside they aren't. With png files there is no problem. I can allow to save only as png but it would be better if i can choose.
Solution :
BufferedImage bImage = SwingFXUtils.fromFXImage(modifiedImage.getImage(), null);
BufferedImage bImage2 = new BufferedImage(bImage.getWidth(), bImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
bImage2.getGraphics().drawImage(bImage, 0, 0, null);
try {
ImageIO.write(bImage2, "jpg", outputFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
You are again one of the many people who are hit by this bug https://bugs.openjdk.java.net/browse/JDK-8119048 which is not considered important enough to be fixed. If you read the comments in there you will find a work-arround. Basically the idea is to copy the image after the conversion into a new image without alpha channel.
I'd really like to know how many more people have to waste their time until this bug finally gets enough attention to be fixed.

Read pixel from a big jp2 image without loading the whole image into memory

I'm trying to read parts from a big image in java. My image size is more than 700 MB. I have used this code which normally reads pixels without loading the whole image into memory:
Rectangle sourceRegion = new Rectangle(0, 0, 512, 512); // The region you want to extract
ImageInputStream stream = ImageIO.createImageInputStream( new File("/home/dhoha/Downloads/BreastCancer.jp2")); // File or input stream
final Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
if (readers.hasNext()) {
ImageReader reader = (ImageReader)readers.next();
reader.setInput(stream, true);
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(sourceRegion); // Set region
BufferedImage image = reader.read(0, param); // Will read only the region specified
However, I got the error:
Exception in thread "main" java.lang.IllegalArgumentException: Dimensions (width=95168 height=154832) are too large
at java.awt.image.SampleModel.<init>(SampleModel.java:130)
at java.awt.image.ComponentSampleModel.<init>(ComponentSampleModel.java:146)
at java.awt.image.PixelInterleavedSampleModel.<init>(PixelInterleavedSampleModel.java:87)
at com.sun.media.imageioimpl.plugins.jpeg2000.J2KRenderedImageCodecLib.createSampleModel(J2KRenderedImageCodecLib.java:741)
at com.sun.media.imageioimpl.plugins.jpeg2000.J2KRenderedImageCodecLib.createOriginalSampleModel(J2KRenderedImageCodecLib.java:729)
at com.sun.media.imageioimpl.plugins.jpeg2000.J2KRenderedImageCodecLib.<init>(J2KRenderedImageCodecLib.java:261)
at com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLib.read(J2KImageReaderCodecLib.java:364)
at testJai2.test3.main(test3.java:21)
Any help please to read parts from this big image?
There are different ways to load parts of image to memory and then process it afterwards. You can try out the following method to read fragments:
public static BufferedImage readFragment(InputStream stream, Rectangle rect)
throws IOException {
ImageInputStream imageStream = ImageIO.createImageInputStream(stream);
ImageReader reader = ImageIO.getImageReaders(imageStream).next();
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(rect);
reader.setInput(imageStream, true, true);
BufferedImage image = reader.read(0, param);
reader.dispose();
imageStream.close();
return image;
}
And calling it like this:
URL url = new URL("..."); // You can use your own stream instead of URL
Image chunk = readFragment(url.openStream(), new Rectangle(150, 150, 300, 250));
This is marked as a correct answer in this thread.
You can use this technique to finally read the whole image into the memory if you need by doing some simple calculations.
EDIT:
The resolution of the image you are trying to process is larger than an array can have (95168x154832). So basically you will not be able to read the image, since ImageIO.createImageInputStream() tries to load the whole image into an array AFAIK.
What you can do is use a library called ImgLib2. Here you can find some examples. ImgLib2 uses multidimensional arrays to read the (big) image data and so it's larger than ImageIO can handle.

Rotation by AffineTransform makes saved image empty

Ok my problem is simple, after performing AffineTransform, my image is not saving properly (however it is drawn on JPanel properly!). It is really strange, so any hints are really appreciated...
Take a look on code:
public BufferedImage performRotation(BufferedImage bi){
if (angle!=180){
at.translate(0.5*bi.getHeight(), 0.5*bi.getWidth());
if(clockwise){
at.rotate(Math.toRadians(angle));
}else{
at.rotate(Math.toRadians(-angle));
}
at.translate(-0.5*bi.getWidth(), -0.5*bi.getHeight());
}
else if(angle==180){
at.translate(0.5*bi.getWidth(), 0.5*bi.getHeight());
at.rotate(Math.toRadians(angle));
at.translate(-0.5*bi.getWidth(), -0.5*bi.getHeight());
}
AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
BufferedImage bi2 = op.filter(bi, null);
try {
ImageIO.write(bi, "bmp", new File("BEFORE filterORIG.bmp"));
ImageIO.write(bi2, "bmp", new File("AFTER filterNEW.bmp"));
} catch (IOException ex) {
Logger.getLogger(DrawingField.class.getName()).log(Level.SEVERE, null, ex);
}
File BEFORE filterORIG is saved properly -> there is an image, but its pre-rotated.
File AFTER... is saved as blank file.
What is really interesting, is previously mentioned fact that this transformation is poperly shown on JPanel that i use as a display (i can observe effect of desired transformation)
Any help appreciated...
Try writing png images, ie:
ImageIO.write(bi, "png", new File("BEFORE filterORIG.png"));
ImageIO.write(bi2, "png", new File("AFTER filterNEW.png"));
The resulting image (bi2) may have an aplha channel and ImageIO may not allow to encode images with aplha as bmp.
Alternatively, create a destination image with TYPE_INT_RGB color model and use it as a second argument in filter() method.

How to save jpeg Image file size after read--rotate-write operations in Java?

Im trying to read a JPEG image as BufferedImage, rotate and save it as another jpeg image from file system. But there is a problem : after these operations I cannot proceed same file size.
Here the code
//read Image
BufferedImage img = ImageIO.read(new File(path));
//rotate Image
BufferedImage rotatedImage = new BufferedImage(image.getHeight(),
image.getWidth(), BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g2d = (Graphics2D) rotatedImage.getGraphics();
g2d.rotate(Math.toRadians(PhotoConstants.ROTATE_LEFT));
int height=-rotatedImage.getHeight(null);
g2d.drawImage(image, height, 0, null);
g2d.dispose();
//Write Image
Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter)iter.next();
// instantiate an ImageWriteParam object with default compression options
ImageWriteParam iwp = writer.getDefaultWriteParam();
try {
FileImageOutputStream output = null;
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(0.98f); // an integer between 0 and 1
// 1 specifies minimum compression and maximum quality
File file = new File(path);
output = new FileImageOutputStream(file);
writer.setOutput(output);
IIOImage iioImage = new IIOImage(image, null, null);
writer.write(null, iioImage, iwp);
output.flush();
output.close();
writer.dispose();
Is it possible to access compressionQuality parameter of original jpeg image in the beginning. when I set 1 to compression quality, the image gets bigger size. Otherwise I set 0.9 or less the image gets smaller size. How can i proceed the image size after these operations?
Thank you,
What do you mean - do you want to read the compression rate of the original file?
Please note that even with the same compression settings, the filesize might vary, due to the JPEG compression algorithm. So a rotated image does not always have the exact same size as the unrotated/original version, even if all options (like compression rate, quality settings etc.) are the same.
If there is really now way to read the compression quality from the metadata, as a last resort, what you could do is use a binary search for the quality. Start with 0.5, if the file is too small try 0.75 and so on (up to 5 tries or so). This is a bit slow of course, but depending on your use case it might be OK.

Categories