简体   繁体   English

在Java中将灰度转换为颜色渐变?

[英]Convert grayscale to color gradient in Java?

Is there any general algorithm or a provided class for mapping a grayscale value (0-255) to a value in a colour gradient? 是否有用于将灰度值(0-255)映射到颜色渐变中的值的通用算法或提供的类? I am thinking of something of the sorts: 我在想一些事情:

   public Color mapGrayscaleValue (byte value, Color[] gradientColors);

I am wanting this to provide clearer highlights in what would otherwise be a grayscale cloud coverage radar image I have been provided. 我希望这能在提供的灰度云覆盖雷达图像中提供更清晰的亮点。

If you are using java.awt.image , you should look in to IndexColorModel . 如果使用java.awt.image ,则应查看IndexColorModel It does (I think) exactly what you're looking for. 它确实(我认为)是您想要的。

You will need to generate the 256 RGB values for the gradient somehow and create a model around them, then you can create a BufferedImage from the grayscale raster using the new model. 您将需要以某种方式生成渐变的256个RGB值并围绕它们创建一个模型,然后可以使用新模型从灰度栅格中创建BufferedImage

Here's a hopefully straightforward example of this: 这是一个希望如此简单的示例:

索引颜色模型ex

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.net.*;

class ColorModelEx implements Runnable {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ColorModelEx());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame();
        JLabel label;
        try {
            label = new JLabel(new ImageIcon(createImage(
                Color.yellow, Color.red, Color.blue)));
        } catch (Exception e) {
            throw new AssertionError(e);
        }

        frame.add(label);
        frame.pack();
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    static BufferedImage createImage(Color... colors) throws Exception {
        if ((256 % (colors.length - 1)) != 0)
            throw new IllegalArgumentException();

        BufferedImage original =
            ImageIO.read(new URL("http://i.stack.imgur.com/7bI1Y.jpg"));

        final int w = original.getWidth();
        final int h = original.getHeight();

        BufferedImage gray =
            new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g2 = gray.createGraphics();
        g2.drawImage(original, 0, 0, null);

        byte[] r = new byte[256];
        byte[] g = new byte[256];
        byte[] b = new byte[256];

        final int fade = (256 / (colors.length - 1));

        // (generate all 256 RGB values by
        // fading between the colors supplied)
        for (int i = 0; i < 256; ++i) {
            Color c0 = colors[(i / fade)];
            Color c1 = colors[(i / fade) + 1];

            float amt = (i % fade) / ((float) fade);

            r[i] = getChannel(amt, c0.getRed(),   c1.getRed());
            g[i] = getChannel(amt, c0.getGreen(), c1.getGreen());
            b[i] = getChannel(amt, c0.getBlue(),  c1.getBlue());
        }

        // (remap same pixels to new model)
        return new BufferedImage(
            new IndexColorModel(8, 256, r, g, b),
            gray.getRaster(), false, null);
    }

    static byte getChannel(float amt, int ch0, int ch1) {
        return (byte)
            ((ch0 * (1 - amt)) + (ch1 * amt));
    }
}

(Image from here .) (图片来自这里 。)

Some other useful places: 其他有用的地方:

Having thought about it, I simply created a 255x1 BufferedImage and then used the GradientPaint class to create myself a colour lookup table. 考虑了一下之后,我简单地创建了一个255x1的BufferedImage,然后使用GradientPaint类为自己创建了一个颜色查找表。 With this approach I can even load a manually created colour table. 通过这种方法,我什至可以加载手动创建的颜色表。 For anyone else: 对于其他任何人:

// Set up the reference image that will be used as the color map

int width = 255;
int height = 1;

BufferedImage colorGradientImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

Graphics2D g2 = (Graphics2D) colorGradientImage.getGraphics();

Paint p = new LinearGradientPaint(
            0, 0, width, 0, new float[] { 0.0f, 0.7f, 0.8f },
            new Color[] { Color.YELLOW, Color.BLUE, Color.RED }
            );

g2.setPaint(p);
g2.fillRect(0, 0, width, height);

g2.dispose();

// Now process the data, using the colour map we created above for the colour values

// pixel data is matrix of values, from 0-255
int[][] pixelData = getSourceValues();

BufferedImage myImage = new BufferedImage(pixelData[0].length, pixelData.length, BufferedImage.TYPE_INT_RGB);
for (int y=0; y<pixelData.length; y++) {
   for (int x=0; x<myImage[y].length; x++) {
       myImage.setRGB(x,y, colorGradientImage.getRGB(pixelData,0));
   }
}

I could probably have converted the colorGradientImage to 255 length array, but for now this does the job. 我可能已经将colorGradientImage转换为255个长度的数组,但是现在可以完成工作。

If anyone knows of an alternative or better approach I am always interested. 如果有人知道替代或更好的方法,我总是很感兴趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM