3 Replies - 390 Views - Last Post: 26 December 2012 - 05:53 AM Rate Topic: -----

#1 cfoley  Icon User is offline

  • Cabbage
  • member icon

Reputation: 1957
  • View blog
  • Posts: 4,059
  • Joined: 11-December 07

Converting colours to grayscale

Posted 24 December 2012 - 06:24 AM

This issue came about as I was trying to test a routine for converting images to grayscale. The code below creates a horizontal strip of coloured squares and then uses two different methods to create grayscale images. The fist pastes the original into a grayscale buffered image. The second converts the colours to shades of gray and then draws them on a "colour" BufferedImage.

The two grayscale images use visibly different shades of gray. What is surprising is that both of my methods to do the conversion make API calls that look like they should produce the same results.

Can anyone shed light on the discrepancy?

If it helps, I'm not well-versed in ColorModel or ColorSpace so it is possible I have used them incorrectly.
My mistake. That was referring to a third method I have not included here.

import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.util.List;

import javax.swing.*;


@SuppressWarnings("serial")
public class GrayscaleDemo extends JFrame {

	public static void main(String[] args) {
		@SuppressWarnings("unused")
		GrayscaleDemo grayscaleDemo = new GrayscaleDemo();
	}

	private Image fullColour;
	private Image convertedToGray;
	private Image alwaysGray;

	public GrayscaleDemo() {
		super("Grayscale Demo");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		makeImages();
		makeLayout();
		setAsVisible();
	}

	private void makeImages() {
		Color[] colours = {Color.red, Color.green, Color.blue, Color.black, Color.gray, Color.white};
		Color[] grays = colourArrayToGray(colours);
		fullColour = makeColourStrip(colours);
		convertedToGray = imageToGray(fullColour);
		alwaysGray = makeColourStrip(grays);
	}

	private Color[] colourArrayToGray(Color... cols) {
		List<Color> result = new ArrayList<>();
		for(Color c : cols) {
			Color gray = singleColourToGray(c);
			result.add(gray);
		}
		return result.toArray(new Color[cols.length]);
	}

	private static Color singleColourToGray(Color c) {
		BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY);
		Graphics2D g2 = image.createGraphics();
		g2.setColor(c);
		g2.fillRect(0, 0, 1, 1);
		g2.dispose();
		Color result = new Color(image.getRGB(0, 0));
		return result;
	}

	private Image makeColourStrip(Color... cols) {
		final int squareSize = 50;
		int width = cols.length * squareSize;
		BufferedImage result = new BufferedImage(width, squareSize, BufferedImage.TYPE_3BYTE_BGR);
		int x1 = 0;
		Graphics2D g2 = result.createGraphics();
		for(Color c : cols) {
			g2.setPaint(c);
			g2.fillRect(x1, 0, squareSize, squareSize);
			x1 += squareSize;
		}
		g2.dispose();
		return result;
	}

	private BufferedImage imageToGray(Image im) {
		BufferedImage result = new BufferedImage(im.getWidth(null), im.getHeight(null), BufferedImage.TYPE_BYTE_GRAY);
		Graphics2D g2 = result.createGraphics();
		g2.drawImage(im, 0, 0, null);
		g2.dispose();
		return result;
	}

	private void makeLayout() {
		int rows = 0;
		int cols = 1;
		setLayout(new GridLayout(rows, cols));

		addImage(fullColour);
		addImage(convertedToGray);
		addImage(alwaysGray);

		pack();
	}

	private void addImage(Image im) {
		JLabel label = new JLabel(new ImageIcon(im));
		add(label);
	}

	private void setAsVisible() {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				setVisible(true);
			}
		});
	}

}

This post has been edited by cfoley: 24 December 2012 - 06:27 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Converting colours to grayscale

#2 farrell2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 824
  • View blog
  • Posts: 2,542
  • Joined: 29-July 11

Re: Converting colours to grayscale

Posted 24 December 2012 - 09:25 AM

I ma not the greatest with graphics, but I am going to assume that it might have something to do with this in singleColourToGray().

BufferedImage.TYPE_BYTE_GRAY

Color result = new Color(image.getRGB(0, 0));



"java.awt.image.BufferedImage.getRGB(int x, int y)

Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace. Color conversion takes place if this default model does not match the image ColorModel. "

This post has been edited by farrell2k: 24 December 2012 - 09:25 AM

Was This Post Helpful? 1
  • +
  • -

#3 cfoley  Icon User is offline

  • Cabbage
  • member icon

Reputation: 1957
  • View blog
  • Posts: 4,059
  • Joined: 11-December 07

Re: Converting colours to grayscale

Posted 26 December 2012 - 05:29 AM

I think you could be right but I'm at a bit of a loss. That method seems to be the one always used in examples of colour sampling. However, all the examples I found used colour images. I've added some stuff to my code (below).

There is another image in colour drawn from getRGB() colours from the first colour image. This appears identical to the first colour image. Another new example draws the original colours onto a gray canvas. It's identical to the grayscale image converted from the colour image. This last bit supports your theory.

My goal is to sample a colour from a grayscale image in such a way that I can create an instance of Color that matches it.

import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.util.List;

import javax.swing.*;


@SuppressWarnings("serial")
public class GrayscaleDemo extends JFrame {
	
	private static final int SQUARE_SIZE = 50;

	public static void main(String[] args) {
		@SuppressWarnings("unused")
		GrayscaleDemo grayscaleDemo = new GrayscaleDemo();
	}
	
	private Color[] colours = {Color.red, Color.green, Color.blue, Color.black, Color.gray, Color.white};

	public GrayscaleDemo() {
		super("Grayscale Demo");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		makeLayout();
		setAsVisible();
	}
	
	private void makeLayout() {
		int rows = 0;
		int cols = 1;
		setLayout(new GridLayout(rows, cols));

		addImage(drawOnColourCanvas());
		addImage(drawColoursFromGetRgbMethod());
		addImage(convertColouredImageToGray());
		addImage(drawOnGrayCanvas());
		addImage(drawGraysFromGetRgbMethod());

		pack();
	}
	
	private void addImage(Image im) {
		JLabel label = new JLabel(new ImageIcon(im));
		add(label);
	}

	private Image drawOnColourCanvas() {
		return drawStrip(makeColourCanvas(), colours);
	}
	
	private BufferedImage makeColourCanvas() {
		return makeCanvas(BufferedImage.TYPE_3BYTE_BGR);
	}
	
	private BufferedImage makeGrayCanvas() {
		return makeCanvas(BufferedImage.TYPE_BYTE_GRAY);
	}
	
	private BufferedImage makeCanvas(int canvasType) {
		int width = colours.length * SQUARE_SIZE;
		BufferedImage result = new BufferedImage(width, SQUARE_SIZE, canvasType);
		return result;
	}
	
	private Image drawColoursFromGetRgbMethod() {
		Color[] coloursReadBack = colourArrayToGray(makeColourCanvas(), colours);
		return drawStrip(makeColourCanvas(), coloursReadBack);
	}
	
	private Image convertColouredImageToGray() {
		return imageToGray(drawOnColourCanvas());
	}
	
	private BufferedImage imageToGray(Image im) {
		BufferedImage result = new BufferedImage(im.getWidth(null), im.getHeight(null), BufferedImage.TYPE_BYTE_GRAY);
		Graphics2D g2 = result.createGraphics();
		g2.drawImage(im, 0, 0, null);
		g2.dispose();
		return result;
	}
	
	private Image drawOnGrayCanvas() {
		return drawStrip(makeGrayCanvas(), colours);
	}
	
	private Image drawGraysFromGetRgbMethod() {
		Color[] coloursReadBack = colourArrayToGray(makeGrayCanvas(), colours);
		return drawStrip(makeColourCanvas(), coloursReadBack);
	}

	private Color[] colourArrayToGray(BufferedImage canvas, Color... cols) {
		List<Color> result = new ArrayList<>();
		for(Color c : cols) {
			Color gray = readColourValueFromImage(canvas, c);
			result.add(gray);
		}
		return result.toArray(new Color[cols.length]);
	}

	private static Color readColourValueFromImage(BufferedImage image, Color c) {
		Graphics2D g2 = image.createGraphics();
		g2.setColor(c);
		g2.fillRect(0, 0, 1, 1);
		g2.dispose();
		Color result = new Color(image.getRGB(0, 0));
		return result;
	}

	private Image drawStrip(BufferedImage canvas, Color... cols) {
		int x1 = 0;
		Graphics2D g2 = canvas.createGraphics();
		for(Color c : cols) {
			g2.setPaint(c);
			g2.fillRect(x1, 0, SQUARE_SIZE, SQUARE_SIZE);
			x1 += SQUARE_SIZE;
		}
		g2.dispose();
		return canvas;
	}

	private void setAsVisible() {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				setVisible(true);
			}
		});
	}

}


Was This Post Helpful? 0
  • +
  • -

#4 cfoley  Icon User is offline

  • Cabbage
  • member icon

Reputation: 1957
  • View blog
  • Posts: 4,059
  • Joined: 11-December 07

Re: Converting colours to grayscale

Posted 26 December 2012 - 05:53 AM

OK, I sort of have an answer. This method works, at least for the image types I'm using:

	private static Color readColourValueFromImage(BufferedImage image, Color c) {
		Graphics2D g2 = image.createGraphics();
		g2.setColor(c);
		g2.fillRect(0, 0, 1, 1);
		g2.dispose();

		int[] pixel = image.getRaster().getPixel(0, 0, (int[])null);
		int L = pixel.length;
		Color result = new Color(pixel[0%L], pixel[1%L], pixel[2%L]);
		
		return result;
	}



If you dig down to the raster and call getPixel() you get an array of colour bands. Three bands for RGB, one for grayscale. I'm sure that code will fall apart for other image types but it serves my purposes for now.

Thank farrell2k for the help!
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1