I have viewed this question, but it does not seem to actually answer the question that I have. I have a, image file, that may be any resolution. I need to load that image into a BufferedImage Object at a specific resolution (say, for this example, 800x800). I know the Image class can use getScaledInstance() to scale the image to a new size, but I then cannot figure out how to get it back to a BufferedImage. Is there a simple way to scale a Buffered Image to a specific size?
NOTE I I do not want to scale the image by a specific factor, I want to take an image and make is a specific size.
Something like this? :
/**
* Resizes an image using a Graphics2D object backed by a BufferedImage.
* #param srcImg - source image to scale
* #param w - desired width
* #param h - desired height
* #return - the new resized image
*/
private BufferedImage getScaledImage(Image srcImg, int w, int h){
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}
You can create a new BufferedImage of the size you want and then perform a scaled paint of the original image into the new one:
BufferedImage resizedImage = new BufferedImage(new_width, new_height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(image, 0, 0, new_width, new_height, null);
g.dispose();
see this website Link1
Or
This Link2
Related
I am fairly new to Java so my knowledge is limited. I have this assignment where I have to get data from an Access database and fill a dialogBox full of fields. I had no problem with typical fields, but I hit a dead end trying to make the attachment field work.
I've tried using the .getByte() methods I've seen on the web, and I don't quite grasp yet the Attachment uncanaccess class method. Can anyone help me or guide me in the right direction please? Here's some code for reference on how I've filled the other fields:
JTextField_cod_distrib.setText(result.getLong("Cod_distribuitor")+"");
JCheckBox_in_stoc.setSelected(result.getBoolean("In_stoc"));
JTextField_pret.setText(result.getFloat("Pret")+""); JTextField_denumire_produs.setText(result.getString("Denumire_produs")+"");
JTextField_cod_produs.setText(result.getInt("Cod_produs")+"");
JTextField_ambalaj.setText(result.getString("Ambalaj")+"");
If you know that there is always exact one attachment in the array, you could do
jlabel.setIcon(new ImageIcon(getScaled(ImageIO.read(new ByteArrayInputStream(((Attachment[])result.getObject("attachment"))[0].getData())),120,120)));
Otherwise you will have to add a JLabel for every attachment:
JPanel attachmentPanel=new JPanel(new FlowLayout(FlowLayout.LEFT));
Attachment[] attachments=(Attachment[])result.getObject("attachment");
for(Attachment attachment:attachments) {
Image original=ImageIO.read(new ByteArrayInputStream(attachment.getData()));
attachmentPanel.add(new JLabel(new ImageIcon(getScaled(original,120,120))));
}
//add the attachmentPanel to your component
From https://docs.oracle.com/javase/tutorial/uiswing/examples/components/IconDemoProject/src/components/IconDemoApp.java
/**
*
* Resizes an image using a Graphics2D object backed by a BufferedImage.
* #param srcImg - source image to scale
* #param w - desired width
* #param h - desired height
* #return - the new resized image
*/
private BufferedImage getScaledImage(BufferedImage srcImg, int w, int h){
double sw=srcImg.getWidth();
double sh=srcImg.getHeight();
double fw=w/sw;
double fh=h/sh;
if(fw<fh) w=(int)(sw*fh);
else if(fh<fw) h=(int)(sh*fw);
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}
While trying to scale the image drawn on a canvas, I came across Graphics2D.drawImage(originalImage) [Graphics2D object obtained from BufferedImage object].
I used it to draw the image into the graphics created from BufferedImage, this new image could be now be drawn onto a Graphics object of the Panel/Frame to get a zoomed image.
I populated the original image using BufferedImage.setRGB.
So, what is it actually doing? Is it selectively omitting the pixels from the original image?
Similar to this code.
int newImageWidth = imageWidth * zoomLevel;
int newImageHeight = imageHeight * zoomLevel;
BufferedImage resizedImage = new BufferedImage(newImageWidth , newImageHeight, imageType);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, newImageWidth , newImageHeight , null);
g.dispose();
Original Answer for the above code
I want to copy a part of BufferedImage, but the copying form is not a simple square but rather a square rotated on some angle. As an output I want to get the BufferedImage with width and height equals to the copying square size and contents from the initial image, where copying square intersects the initial image.
What is the simplest way to do it?
A simple approach would be to create a new image with the desired size, transform a Graphics2D of this image according to the selected square region, and then simply paint the original image into this graphics:
private static BufferedImage extractRegion(
BufferedImage source, Point2D center, Point2D size, double angleRad)
{
int w = (int)size.getX();
int h = (int)size.getY();
BufferedImage result =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.translate(size.getX() / 2, size.getY() / 2);
g.rotate(angleRad);
g.translate(-center.getX(), -center.getY());
g.drawImage(source, 0, 0, null);
g.dispose();
return result;
}
I wrote a method to resize BufferedImages for me but after doing so .png images end up losing their transparency and instead they get a black background.
public BufferedImage getSizedImg(BufferedImage otherImage,int width,int height){
BufferedImage outputImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = outputImg.createGraphics();
g.drawImage(otherImage, 0, 0, width, height, null);
g.dispose();
return outputImg;
}
How can I fix the method so that the images keep their transparency?
Simple. When you create your new re-sized BufferedImage here:
BufferedImage outputImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
don't use BufferedImage.TYPE_INT_RGB but rather BufferedImage.TYPE_INT_ARGB. The "A" stands for "alpha" and this gives you the transparency. For more on this, please see the BufferedImage API.
Recently I have been attempting to scale pixel arrays (int[]) in Java. I used .setRGB() to add all my pixel data into the BufferedImage. BufferedImage then offers a function called .getScaledInstance(). This should work great for my purposes, but I ran into a problem. .getScaledInstance() returns a Image, not a BufferedImage. With an Image object, I cannot use .getRGB() to add all the pixel data (in int[] form) from the scaled Image back into an array. Is there a way to get raw pixel data from an Image file? Am I missing something? I looked at other questions and did a bit of googling, and they only seemed to be wanting to get picture data in a different form of array (int[][]) or in bytes. Any help would be appreciated, thanks. Also, Sprite is a class I made that is being used. Here is my code:
public Sprite scaleSprite(Sprite s, int newWidth, int newHeight){
BufferedImage image = new BufferedImage(s.getWidth(), s.getHeight(), BufferedImage.TYPE_INT_RGB);
for(int y = 0; y < s.getHeight(); y++){
for(int x = 0; x < s.getWidth(); x++){
image.setRGB(x, y, s.getPixel(x, y));
}
}
Image newImage = image.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
Sprite newS = new Sprite(newWidth, newHeight);
int[] pixels = new int[newWidth * newHeight];
newImage.getRGB(0, 0, newWidth, newHeight, pixels, 0, newWidth); //This is where I am running into problems. newImage is an Image and I cannot retrieve the raw pixel data from it.
newS.setPixels(pixels);
return newS;
}
You can draw the resulting Image onto a BufferedImage like this:
Image newImage = image.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
BufferedImage buffImg = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2 = (Graphics2D) buffImg.getGraphics();
g2.drawImage(newImage, 0, 0, 10, 10, null);
g2.dispose();
Or you can scale the image directly by drawing it on another BufferedImage:
BufferedImage scaled = new BufferedImage(newWidth, newWidth, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2 = (Graphics2D) scaled.getGraphics();
g2.drawImage(originalImage, 0, 0, newWidth, newWidth, 0, 0, originalImage.getWidth(), originalImage.getHeight(), null);
g2.dispose();
The second approach will work correctly if the two BufferedImages have the same aspect ratio.
To be clear, getScaledInstance() is a method of Image, not BufferedImage. You don't generally want to revert to working directly with the Image superclass once you're working with BufferedImage; Image is really not easy to work with.
Please see if this will help: How to scale a BufferedImage
Or from Scaling a BufferedImage, where they yield the following example:
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
public class Main {
public static void main(String[] argv) throws Exception {
BufferedImage bufferedImage = new BufferedImage(200, 200,
BufferedImage.TYPE_BYTE_INDEXED);
AffineTransform tx = new AffineTransform();
tx.scale(1, 2);
AffineTransformOp op = new AffineTransformOp(tx,
AffineTransformOp.TYPE_BILINEAR);
bufferedImage = op.filter(bufferedImage, null);
}
This will give you the ability to scale entirely at the level of BufferedImage. From there you can apply whatever sprite specific or array data algorithm you wish.