0

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

user592704
  • 3,674
  • 11
  • 70
  • 107

1 Answers1

3

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.

enter image description 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();
            }
        });
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Sorry about my previous misunderstanding of the question. Please comment if this example does not recapitulate your test case. – trashgod Apr 30 '11 at 04:10
  • I have just noticed the ImageIcon doc and it says ImageIcon cannot use BufferedImage in its constructor just Image http://download.oracle.com/javase/6/docs/api/javax/swing/ImageIcon.html... So I guess I need to repaint here? – user592704 May 01 '11 at 00:57
  • `ImageIcon` is just a convenient way to display the image, and a `BufferedImage` _is_ an `Image`. – trashgod May 01 '11 at 03:01
  • I've elaborated above; the example you cited work well with the image you provided. – trashgod May 01 '11 at 03:18
  • It's greate :) But why mine doesn't then? OK I am going to check it more deeply then and report my results. – user592704 May 02 '11 at 01:49
  • @trashgod I have edited my question... What you think? Do you have the same exception? – user592704 May 03 '11 at 01:27
  • Sorry I overlooked your update previously; I've added more above. – trashgod May 03 '11 at 01:41
  • @trashgod OK. So I have modified some code. PLease watch my question. The image becomes alpha but it seems alpha image makes background visible but its backgroung is black :( What have I missed here? – user592704 May 03 '11 at 02:38
  • I think `TYPE_4BYTE_ABGR_PRE` is wrong; `TYPE_INT_ARGB` is more typical. – trashgod May 03 '11 at 02:42
  • @trashgod I edited this emm... the foreground becomes alpha but backround is still black :( Please watch my TestImage code modifications – user592704 May 03 '11 at 02:46
  • I have corrected your `ImageTest` and adapted it to include a scale factor. As it would make a suitable answer to this [question](http://stackoverflow.com/questions/5864490), I will update my answer there with the results. Please accept this answer, as it explains the `IllegalArgumentException` mentioned in your question. – trashgod May 03 '11 at 11:44
  • Emm, as I was saying, the code in my question is making foreground as transparent but the background is black. That shouldn't be so I need to think it more deeply maybe it is the jpg format which is not supporting the tranparency... I have converted the sample image from jpg to png with my paint the windows editor... So maybe it is the reason of the black image background but still I have to find out more deeply... So I guess the question is not solved totally because the exception is gone, yes, but I cannot get the real JLabel image transparency because of its black background... – user592704 May 03 '11 at 17:43
  • A black image background is usually an incorrectly initialized `BufferedImage`. – trashgod May 04 '11 at 00:46
  • @trashgod OK, I have fixed it yet :) – user592704 May 05 '11 at 16:11
  • I have updated this [answer](http://stackoverflow.com/questions/5864490/how-to-setsize-of-image-using-rescaleop/5864503#5864503) with a related example. – trashgod May 05 '11 at 16:37