How to setSize of image using RescaleOp
First filter()
, as shown here, and then scale using drawImage()
or AffineTransformOp
, as shown here.
Addendum: Alternatively, you can scale the image first (using either approach above) and then use your RescaleOp
in drawImage()
.
As an aside, RescaleOp
scales the image's color bands; it does not change the image's dimensions. To avoid confusion, dimensional scaling is sometimes called resampling.
Addendum: Here's an example of using drawImage()
to resample and RescaleOp
to adjust the alpha of an image.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* @see https://stackoverflow.com/questions/5838842
* @see https://stackoverflow.com/questions/5864490
*/
public class AlphaTest {
private static void display() {
JFrame f = new JFrame("AlphaTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon icon = new ImageIcon("image.jpg");
final AlphaPanel ip = new AlphaPanel(icon, 0.75);
final JSlider slider = new JSlider();
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int v = slider.getValue();
ip.setAlpha((float) v / slider.getMaximum());
ip.repaint();
}
});
f.add(ip, BorderLayout.CENTER);
f.add(slider, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
display();
}
});
}
}
class AlphaPanel extends JPanel {
private BufferedImage bi;
private float[] scales = {1f, 1f, 1f, 0.5f};
private float[] offsets = new float[4];
private RescaleOp rop;
public AlphaPanel(ImageIcon icon, double scale) {
int width = (int) (scale * icon.getIconWidth());
int height = (int) (scale * icon.getIconHeight());
this.setPreferredSize(new Dimension(width, height));
this.bi = new BufferedImage(
width, height, BufferedImage.TYPE_INT_ARGB);
this.bi.createGraphics().drawImage(
icon.getImage(), 0, 0, width, height, null);
rop = new RescaleOp(scales, offsets, null);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(bi, rop, 0, 0);
}
public void setAlpha(float alpha) {
this.scales[3] = alpha;
this.rop = new RescaleOp(scales, offsets, null);
}
}
Java Buffered Image RescaleOp Transparency Issue
You could try the RescaleOp
that handles alpha, illustrated here, and use the same lightLevel
for all color components.
How to scale a BufferedImage
AffineTransformOp
offers the additional flexibility of choosing the interpolation type.
BufferedImage before = getBufferedImage(encoded);
int w = before.getWidth();
int h = before.getHeight();
BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(2.0, 2.0);
AffineTransformOp scaleOp =
new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
after = scaleOp.filter(before, after);
The fragment shown illustrates resampling, not cropping; this related answer addresses the issue; some related examples are examined here.
Changing contrast of image with alpha channel causes yellow tint
I fixed the issue by updating to Java 9.
This seems to be a bug in Java 8, that is now fixed in Java 9. I originally used JDK1.8.0_144 and received the yellow tint, I now use JDK-9.0.4 and no longer have the issue. Now the image looks the same with and without alpha channel.
java.lang.IllegalArgumentException: Number of scaling constants does not equal the number of of color or color/alpha components
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 aJSlider
.
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();
}
});
}
}
How to change the brightness of an Image
The doc says:
The pseudo code for the rescaling operation is as follows:
for each pixel from Source object {
for each band/component of the pixel {
dstElement = (srcElement*scaleFactor) + offset
}
}
It's just a linear transformation on every pixel. The parameters for that transformation are scaleFactor
and offset
. If you want 100% brightness, this transform must be an identity, i.e. dstElement = srcElement
. Setting scaleFactor = 1
and offset = 0
does the trick.
Now suppose you want to make the image darker, at 75% brightness like you say. That amounts to multiplying the pixel values by 0.75. You want: dstElement = 0.75 * srcElement
. So setting scaleFactor = 0.75
and offset = 0
should do the trick. The problem with your values is that they go from 0 to 100, you need to use values between 0 and 1.
Related Topics
Java 8: Difference Between Method Reference Bound Receiver and Unbound Receiver
Jdk Dateformatter Parsing Dayofweek in German Locale, Java8 VS Java9
How to Remove Single Character from a String
Where Do Java and .Net String Literals Reside
Does Java Have Built in Libraries for Audio _Synthesis_
Embedded Mongodb When Running Integration Tests
Converting Any Object to a Byte Array in Java
Assert Equals Between 2 Lists in Junit
Best Way to Encode Text Data for Xml in Java
Why Shouldn't I Call Setvisible(True) Before Adding Components
What Is a Covariant Return Type
Filter Values Only If Not Null Using Lambda in Java8
Why I Can't Create an Array with Large Size
The Method Getdispatchertype() Is Undefined for the Type Httpservletrequest