For my assignment I need to turn this singular picture.
Into this:
I've tried using negatives and reversing it manually but that didn't work out.
DrawingImages.java
```java
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
public class DrawingImages
{
private Picture newCanvas = null;
private Graphics g = null;
private Graphics2D g2 = null;
private Picture pic1 = null;
private Color color = null;
int height= 250;
int width = 250;
DrawingImages(Picture canv, Picture p1)
{
newCanvas = canv;
newCanvas.setAllPixelsToAColor(Color.BLACK);
g = newCanvas.getGraphics();
g2 = (Graphics2D)g;
pic1 = p1;
}
public Picture drawPicture()
{
//Flip the image both horizontally and vertically
g2.drawImage(image, x+(width/2), y+(height/2), -width, -height, null);
//Flip the image horizontally
g2.drawImage(image, x+(width/2), y-(height/2), -width, height, null);
//Flip the image vertically
g2.drawImage(image, x-(width/2), y+(height/2), width, -height, null);
return newCanvas;
}
}
```
DrawingImagesTester.java
```java
import java.awt.Color;
public class DrawImagesTester
{
public static void main(String[] args)
{
Picture canvas = new Picture(500, 500);
Picture picture1 = new Picture("flower1.jpg");
DrawingImages draw = new DrawingImages(canvas, picture1, Color.YELLOW);
canvas = draw.drawPicture();
canvas.show();
}
}
You need to mirror the image. The process is actually really simple and is a commonly used trick. You simply need to scale the image in a negative direction, along the axis you want mirrored (and then translate the image so it will re-appear within the user space)
For example...
BufferedImage img = ImageIO.read(new File("/Users/shanew/Downloads/kAJZbDc.jpg"));
BufferedImage mirrored = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
Graphics2D g2d = mirrored.createGraphics();
g2d.scale(-1, 1);
g2d.translate(-mirrored.getWidth(), 0);
g2d.drawImage(img, 0, 0, null);
g2d.dispose();
BufferedImage combined = new BufferedImage(img.getWidth() * 2, img.getHeight(), img.getType());
g2d = combined.createGraphics();
g2d.drawImage(img, 0, 0, null);
g2d.drawImage(mirrored, img.getWidth(), 0, null);
g2d.dispose();
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(combined)));
Related
I am trying to change the alpha value of an image, I have the code
public void changeImage (File currentImage) throws IOException {
BufferedImage img = ImageIO.read(currentImage);
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int pixel = img.getRGB(x,y);
Color color = new Color(pixel);
int red = 10;
int green = 20;
int blue = 30;
int alpha = 40;
color = new Color(red, green, blue, alpha);
img.setRGB(x, y, color.getRGB());
}
}
File outputImage = new File(currentImage.getAbsolutePath().substring(0, currentImage.getAbsolutePath().length() - 4) + "_encrypted.png");
ImageIO.write(img, "png", outputImage);
}
The colors change just fine and when I get Java to print the new photo's alpha value, it says it's 40 but it doesn't look less transparent at all. Like the colors obviously change but the transparency does not. Example Like see, it's not less transparent at all, this is my first time with colors.
I have tried to do Color color = new Color(pixel, true); instead but it didn't really change anything.
public void changeImage (File currentImage) throws IOException {
BufferedImage img = ImageIO.read(currentImage);
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int pixel = img.getRGB(x,y);
Color color = new Color(pixel);
int red = 10;
int green = 20;
int blue = 30;
int alpha = 40;
color = new Color(red, green, blue, alpha);
img.setRGB(x, y, color.getRGB());
}
}
File outputImage = new File(currentImage.getAbsolutePath().substring(0, currentImage.getAbsolutePath().length() - 4) + "_encrypted.png");
ImageIO.write(img, "png", outputImage);
}
So, my immediate thoughts are:
Why?!
Did you really want to fill the entire image with a single color?
Does the original image support a alpha based color model?
So, if you really just wanted to fill the image with a single translucent color, you could have simply just done...
BufferedImage translucent = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = translucent.createGraphics();
g2d.setColor(new Color(10, 20, 30, 40));
g2d.fillRect(0, 0, master.getWidth(), master.getHeight());
g2d.dispose();
which would be faster.
If, instead, you "really" wanted to make the image appear transparent, then you should probably have started with something like...
public static BufferedImage changeImage(BufferedImage master) {
BufferedImage img = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int pixel = master.getRGB(x, y);
Color color = new Color(pixel);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
int alpha = 40;
color = new Color(red, green, blue, alpha);
img.setRGB(x, y, color.getRGB());
}
}
return img;
}
This creates a new BufferedImage with a color model which supports transparency. It then converts each pixel of the master image to have a alpha color and updates the new image with it.
But again, you could just do something like...
BufferedImage img = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = alphaed.createGraphics();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.156862745098039f));
g2d.drawImage(master, 0, 0, this);
g2d.dispose();
which would be faster.
Runnable example
So, left, original image, middle, your "modified" code, right, AlphaComposite based result
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public static BufferedImage changeImage(BufferedImage master) {
BufferedImage img = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int pixel = master.getRGB(x, y);
Color color = new Color(pixel);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
int alpha = 40;
color = new Color(red, green, blue, alpha);
img.setRGB(x, y, color.getRGB());
}
}
return img;
}
public class TestPane extends JPanel {
private BufferedImage master;
private BufferedImage modified;
private BufferedImage alphaed;
public TestPane() throws IOException {
master = ImageIO.read(getClass().getResource("/images/MegaTokyo.png"));
modified = changeImage(master);
alphaed = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = alphaed.createGraphics();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.156862745098039f));
g2d.drawImage(master, 0, 0, this);
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(master.getWidth() * 3, master.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(master, 0, 0, this);
g2d.drawImage(modified, master.getWidth(), 0, this);
g2d.drawImage(alphaed, master.getWidth() * 2, 0, this);
g2d.dispose();
}
}
}
Now, it occurs to me that you might be trying to put a color "overlay" on top of the image
In which case you try doing something like...
BufferedImage colorOverlay = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = colorOverlay.createGraphics();
g2d.setColor(new Color(10, 20, 30, 192));
g2d.fillRect(0, 0, colorOverlay.getWidth(), colorOverlay.getHeight());
g2d.dispose();
alphaed = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = alphaed.createGraphics();
g2d.drawImage(master, 0, 0, this);
g2d.drawImage(colorOverlay, 0, 0, this);
g2d.dispose();
which could be simplifed to something like...
alphaed = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = alphaed.createGraphics();
g2d.drawImage(master, 0, 0, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.75f));
g2d.setColor(new Color(10, 20, 30, 192));
g2d.fillRect(0, 0, alphaed.getWidth(), alphaed.getHeight());
g2d.dispose();
(nb: I tried using 40 as the alpha component, but it made such little difference, I changed it to 192 for demonstration purposes)
Runnable example
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public static BufferedImage changeImage(BufferedImage master) {
BufferedImage img = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int pixel = master.getRGB(x, y);
Color color = new Color(pixel);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
int alpha = 40;
color = new Color(red, green, blue, alpha);
img.setRGB(x, y, color.getRGB());
}
}
return img;
}
public class TestPane extends JPanel {
private BufferedImage master;
private BufferedImage alphaed;
public TestPane() throws IOException {
master = ImageIO.read(getClass().getResource("/images/MegaTokyo.png"));
//--- This -----
BufferedImage colorOverlay = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = colorOverlay.createGraphics();
g2d.setColor(new Color(10, 20, 30, 192));
g2d.fillRect(0, 0, colorOverlay.getWidth(), colorOverlay.getHeight());
g2d.dispose();
alphaed = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = alphaed.createGraphics();
g2d.drawImage(master, 0, 0, this);
g2d.drawImage(colorOverlay, 0, 0, this);
g2d.dispose();
//--------------
//--- Or This -----
// alphaed = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
// g2d = alphaed.createGraphics();
// g2d.drawImage(master, 0, 0, this);
// g2d.setComposite(AlphaComposite.SrcOver.derive(0.75f));
// g2d.setColor(new Color(10, 20, 30, 192));
// g2d.fillRect(0, 0, alphaed.getWidth(), alphaed.getHeight());
// g2d.dispose();
//-----------------
}
#Override
public Dimension getPreferredSize() {
return new Dimension(master.getWidth() * 2, master.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(master, 0, 0, this);
g2d.drawImage(alphaed, master.getWidth(), 0, this);
g2d.dispose();
}
}
}
Check the type of the original image that you are loading. The image you've linked is of type 5 (TYPE_3BYTE_BGR).
The definition of TYPE_3BYTE_BGR from Javadocs is as follows:
Represents an image with 8-bit RGB color components, corresponding to
a Windows-style BGR color model) with the colors Blue, Green, and Red
stored in 3 bytes. There is no alpha. The image has a
ComponentColorModel. When data with non-opaque alpha is stored in an
image of this type, the color data must be adjusted to a
non-premultiplied form and the alpha discarded, as described in the
java.awt.AlphaComposite documentation.
Make sure that you are either loading in an image that has a type that supports the alpha channel, or convert your image to one of such a type.
Otherwise, what you are doing is correct.
I want to cut the pic to circle by using java graphics 2d, but the result is unsatisfying. I would like the final pic come as similar as the "object-fit: cover" comes out in css.
This is the original pic
original pic
Below are my codes and the final result.
BufferedImage testImage = ImageIO.read(new File("/Users/huangruixiang/Desktop/test.png"));
BufferedImage formatAvatarImage = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = formatAvatarImage.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, 200, 200);
graphics.setClip(shape);
graphics.drawImage(testImage, 0, 0, 200, 200, null);
graphics.dispose();
ImageIO.write(formatAvatarImage,"png",new File("/Users/huangruixiang/Desktop/circle.png"));
resule
And the effect I want is similar to this
Expected effect
Here you go.
You have to use a different drawImage method than the one you used.
Here's the complete runnable code.
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class CenterCutImage {
public static void main(String[] args) {
CenterCutImage cci = new CenterCutImage();
BufferedImage image = cci.readImage("/do3kO.png");
BufferedImage croppedImage = cci.createCenterCut(image, new Dimension(200, 200));
String path = "D:\\Eclipse\\Eclipse-2020-workspace\\com.ggl.testing3\\resources";
cci.writeImage(croppedImage, path, "circle.png");
}
public BufferedImage createCenterCut(BufferedImage inputImage, Dimension d) {
BufferedImage image = new BufferedImage(d.width, d.height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int x = (inputImage.getWidth() - d.width) / 2;
int y = (inputImage.getHeight() - d.height) / 2;
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, d.width, d.height);
g2d.setClip(shape);
g2d.drawImage(inputImage, 0, 0, d.width, d.height, x, y, x + d.width, y + d.height, null);
g2d.dispose();
return image;
}
public BufferedImage readImage(String filename) {
try {
return ImageIO.read(getClass().getResourceAsStream(filename));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public void writeImage(BufferedImage croppedImage, String path, String filename) {
try {
ImageIO.write(croppedImage, "png", new File(path + "/" + filename));
} catch (IOException e) {
e.printStackTrace();
}
}
}
im trying to make a method in java that will resize rotate and draw a image after given arguments.
It does not work tho. Idk how? Btw is it posible to do this with the normal Graphic class and not Graphic2D ? Thanks!
public void drawResizedAndRotatedImage(Image image, Graphics g, int x, int y, int sizeX, int sizeY, double degrees){
//Resize
BufferedImage im = new BufferedImage(sizeX, sizeY, BufferedImage.TYPE_4BYTE_ABGR);
#SuppressWarnings("unused")
Graphics g2 = (Graphics)im.getGraphics();
//Rotate
ImageIcon imageIcon = new ImageIcon(image);
BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2d = (Graphics2D)bufferedImage.getGraphics();
g2d.rotate(Math.toRadians(degrees), imageIcon.getIconWidth() / 2, imageIcon.getIconHeight() / 2);
//Draw
g.drawImage(image, x, y, sizeX, sizeY, null);
}
Okay, so you create a BufferedImage and grab it's Graphics context...
BufferedImage im = new BufferedImage(sizeX, sizeY, BufferedImage.TYPE_4BYTE_ABGR);
Graphics g2 = (Graphics)im.getGraphics();
And do nothing with it...
You then create a second BufferedImage, grab it's Graphics context, set it's rotational context and paint nothing to it...
BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2d = (Graphics2D)bufferedImage.getGraphics();
g2d.rotate(Math.toRadians(degrees), imageIcon.getIconWidth() / 2, imageIcon.getIconHeight() / 2);
You then paint the original image to the supplied Graphics context...
g.drawImage(image, x, y, sizeX, sizeY, null);
Having achieved nothing at all...
I think you need to start by taking a read through Transforming Shapes, Text, and Images to get some grounding on the basics...
Transformations are compounding, they also only effect whatever is painted to the Graphics context AFTER they have been applied.
The simplest approach would actually be to use a AffineTransform
double scaleWidth = (double)sizeX / (double)image.getWidth(this);
double scaleHeight = (double)sizeY / (double)image.getHeight(this);
BufferedImage img = new BufferedImage(sizeX, sizeY, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
AffineTransform at = new AffineTransform();
at.scale(scaleWidth, scaleHeight);
at.rotate(Math.toRadians(degrees), image.getWidth(this) / 2d, image.getHeight(this) / 2d);
g2d.setTransform(at);
g2d.drawImage(image, sizeX / 2, sizeY / 2, null);
g2d.dispose();
// And finally, the result...
g.drawImage(img, x, y, null);
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestImage {
public static void main(String[] args) {
new TestImage();
}
public TestImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage original;
public TestPane() {
try {
original = ImageIO.read(new File("Your image here"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public Image scaleAndRotate(Image image, int sizeX, int sizeY, double degrees) {
double scaleWidth = (double)sizeX / (double)image.getWidth(this);
double scaleHeight = (double)sizeY / (double)image.getHeight(this);
BufferedImage img = new BufferedImage(sizeX, sizeY, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
AffineTransform at = new AffineTransform();
at.scale(scaleWidth, scaleHeight);
at.rotate(Math.toRadians(degrees), image.getWidth(this) / 2d, image.getHeight(this) / 2d);
g2d.setTransform(at);
g2d.drawImage(image, sizeX / 2, sizeY / 2, null);
g2d.dispose();
return img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int scaleWidth = getWidth() / 2;
int scaleHeight = getHeight() / 2;
Image img = scaleAndRotate(original, scaleWidth, scaleHeight, 45.0);
int x = (getWidth() - img.getWidth(this)) / 2;
int y = (getHeight()- img.getHeight(this)) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
You may also like to take a read through...
Java: maintaining aspect ratio of JPanel background image
Quality of Image after resize very low -- Java
For discussions about scaling algorithms and techniques
You should also know that the size of an image when it rotates also changes, have a look at (one of my favourite answers to refer to) Rotate an image in java for more details about how to calculate the resulting image size of a rotated image...
I am making a basic java application and trying to rotate an image. I wrote the following quick method
private Image rotate(double degs){
ImageIcon img = new ImageIcon("src/inc/img/char_male.png");
Image temp = new BufferedImage(img.getIconWidth(), img.getIconHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D) temp.getGraphics();
g2.rotate(Math.toRadians(degs));
g2.drawImage(img.getImage(), 0, 0, Color.WHITE, null);
System.out.println("Rotating "+degs);
g2.dispose();
return temp;
}
The problem is when I run this and repaint the GUI, the image turns pure black. Am I doing something wrong with the BufferedImage creation? I am changing the GUI in the repaint using a JLabel,
label.setIcon(new ImageIcon(rotate(90)));
You need to rotate and translate at the same time so that the center of rotation is the center of the image. The AffineTransform rotate method has an overload for this as does the Graphics2D rotate method. For e.g., what if you try,...
private Image rotate(double degs){
ImageIcon img = new ImageIcon("src/inc/img/char_male.png"); // why an ImageIcon???
Image temp = new BufferedImage(img.getIconWidth(), img.getIconHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D) temp.getGraphics();
g2.rotate(Math.toRadians(degs), img.getIconWidth()/2, img.getIconHeight()/2); // changed
g2.drawImage(img.getImage(), 0, 0, Color.WHITE, null);
System.out.println("Rotating "+degs);
g2.dispose();
return temp;
}
Sorry, here's the corrected code:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class ImageRotate {
private static final String IMAGE_PATH = "src/yr2011/images/guitar_3406632_n.jpg";
public static void main(String[] args) {
try {
BufferedImage image = ImageIO.read(new File(IMAGE_PATH));
ImageIcon icon = new ImageIcon(image);
JOptionPane.showMessageDialog(null, new JLabel(icon));
icon = new ImageIcon(rotate(image, 90));
JOptionPane.showMessageDialog(null, new JLabel(icon));
} catch (IOException e) {
e.printStackTrace();
}
}
private static Image rotate(Image image, double degs) {
int width = image.getWidth(null);
int height = image.getHeight(null);
BufferedImage temp = new BufferedImage(height, width, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = temp.createGraphics();
g2.rotate(Math.toRadians(degs), height / 2, height / 2);
g2.drawImage(image, 0, 0, Color.WHITE, null);
g2.dispose();
return temp;
}
}
I don't use Java, so that I can't tell if there's something wrong with your code, but a common error when doing image rotation is rotating out of the viewport. When you imagine the original image sitting at the coordinate origin, rotating it by 90 degrees moves the image below the x-axis (or left of the y-axis, depending on the direction). In both cases the rotated image leaves the viewport and you get an empty image. The solution is to shift the rotated image back to place.
I had the same probleme and I solved it in an other way:
My picture had a transparent background but I didn't know it because I look it always on white background. Anyway, I solved my problem when I use
BufferedImage temp = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB);
instead of
BufferedImage temp = new BufferedImage(height, width, BufferedImage.TYPE_INT_RGB);
I think that graphics2d work with a black background if you don't precise transparent type.
I am writing aplha composite test app based on this example
/* Create an ARGB BufferedImage */
BufferedImage img = (BufferedImage)image;//ImageIO.read(imageSrc);
int w = img.getWidth(null);
int h = img.getHeight(null);
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR_PRE);
Graphics g = bi.getGraphics();
g.drawImage(img, 0, 0, null);
/* Create a rescale filter op that makes the image 50% opaque */
float[] scales = { 1f, 1f, 1f, 1f };
float[] offsets = new float[4];
RescaleOp rop = new RescaleOp(scales, offsets, null);
/* Draw the image, applying the filter */
g2d.drawImage(bi, rop, 0, 0);
source link: http://download.oracle.com/javase/tutorial/2d/images/drawimage.html
It works fine with simple images but with photos (jpg etc) I get this exception like:
java.lang.IllegalArgumentException:
Number of scaling constants does not
equal the number of of color or
color/alpha components
To be more clear... Here is my adapted test code class. This code style throws the exception...
public class ImageTest extends JLabel {
public Image image;
private BufferedImage bImage;
ImageObserver imageObserver;
float[] scales = {1f, 1f, 1f, 1f};
float[] offsets = new float[4];
RescaleOp rop;
int width;
int height;
public ImageTest(ImageIcon icon) {
width = icon.getIconWidth();
height = icon.getIconHeight();
this.image = icon.getImage();
this.imageObserver = icon.getImageObserver();
//this.bImage=(BufferedImage)image; //previous version (makes exception?)...
this.bImage = new BufferedImage(
width, height, BufferedImage.TYPE_INT_ARGB);
this.bImage.createGraphics().drawImage(
this.image, 0, 0, width, height, imageObserver);
rop = new RescaleOp(scales, offsets, null);
this.repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(this.bImage, rop, 0, 0);
}
public void setRescaleOp(RescaleOp rop) {
this.rop = rop;
}
}//class end
I am not pretty sure where the exception comes from so I need your advice where to look at?
P.S. I suppose it is the IndexColorModel problem but if so I am not sure how to fix it...
Any useful comment is appreciated :)
Andrew
Using the example below and the image you provided, I am unable to reproduce the effect you describe.
I was puzzled that a BufferedImage of TYPE_4BYTE_ABGR_PRE has a ComponentColorModel, in contrast to the more familiar DirectColorModel, but it's an IndexColorModel that cannot be rescaled.
Addendum: Updated code to use filter(), as the previous version was incorrectly reusing the BufferedImage.
Addendum: In another answer, you said,
I don't want to create a new BufferedImage each time. I want to filter the image on the fly using a JSlider.
The example you cited does this by creating the BufferedImage once in the SeeThroughComponent constructor and then adjusting just the RescaleOp in the slider's change handler. It seems quite responsive.
Addendum: In an edit to your question, you mention that the IllegalArgumentException may arise when encountering an image having an IndexColorModel. I am able to reproduce this using, e.g. TYPE_BYTE_INDEXED. You may be able to work around such images by trapping the exception and rendering them separately as shown here.
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/questions/5838842 */
public class RescaleOpTest extends JPanel {
public static final String LINK =
"http://www.freeimagehosting.net/uploads/576c64ef7b.png";
public RescaleOpTest() {
this.setLayout(new GridLayout(1, 0));
Image img = null;
try {
img = ImageIO.read(new URL(LINK));
// img = ImageIO.read(new File("image.jpg"));
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
int w = img.getWidth(null);
int h = img.getHeight(null);
BufferedImage bi = new BufferedImage(
w, h, BufferedImage.TYPE_4BYTE_ABGR_PRE);
Graphics2D g = bi.createGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
/* Create a rescale filter op that makes the image 75% opaque */
float[] scales = {1f, 1f, 1f, 0.75f};
float[] offsets = new float[4];
RescaleOp rop = new RescaleOp(scales, offsets, null);
bi = rop.filter(bi, null);
this.add(new JLabel(new ImageIcon(img)));
this.add(new JLabel(new ImageIcon(bi)));
}
private void display() {
JFrame f = new JFrame("RescaleOpTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new RescaleOpTest().display();
}
});
}
}