java彩色的世界_JAVA真彩色转256色的实现

色彩转换算法

实现真彩色到256色的转换,关键就是如何从24位真彩色的颜色中选出256种颜色,使图像失真较小。主要的算法有:

(1)取颜色高位算法,例如:分别取R高3位,G高2位,B高3位组成8字节获取256种颜色。

(2)流行色算法。算法的基本思路是:对彩色图像中所有色彩出现的次数进行统计分析,从而选取频率最高的N(256)种颜色,为这N(256)种颜色建立调色板。算法特点:算法简单容易实现,变换效果好,但一些出现频率较低,但对人眼视觉效果明显的信息将丢失。

(3)八叉树颜色量化算法。算法基本思路是:将图像中使用的RGB颜色值分布到层状的八叉树中。八叉树的深度可达9层,即根节点层加上分别表示8位的R、G、B值的每一位的8层节点。较低的节点层对应于较不重要的RGB值的位(右边的位),因此,为了提高效率和节省内存,可以去掉最低部的2 ~ 3层,这样不会对结果有太大的影响。叶节点编码存储像素的个数和R、G、B颜色分量的值;而中间的节点组成了从最顶层到叶节点的路径。这是一种高效的存储方式,既可以存储图像中出现的颜色和其出现的次数,也不会浪费内存来存储图像中不出现的颜色。算法特点:效率高,效果好。

JAVA真彩色转换算法实现

这里,我们用以下两种方式实现色彩的转换:

(1)直接使用JAVA画图功能实现

(2)使用流行色算法实现

(一)使用JAVA画图功能实现转换的方法

这里我们用JAVA的图像库实现颜色的转换,我们先看看直接使用JAVA画图功能实现转换的代码及实现效果。

实现的基本思路是

(1)创建TYPE_BYTE_INDEXED类型的BufferedImage图像对象。

(2)获取该对象的画图对象Graphics2D,将真彩色图像绘制到该图像上。

(3)对新建的对象进行输出,就得到了256色图像。

下面是实现代码

import java.awt.Graphics2D;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import javax.imageio.ImageIO;

public class ColorTrueTo256 {

public static BufferedImage trueTo256(BufferedImage imgSrc) {

int width = imgSrc.getWidth();

int height = imgSrc.getHeight();

BufferedImage imgDst = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED);

Graphics2D g2d = imgDst.createGraphics();

g2d.drawImage(imgSrc, 0, 0, width, height, null);

g2d.dispose();

return imgDst;

}

public static void main(String[] argv) throws IOException {

BufferedImage imgSrc = ImageIO.read(new File("landscape.jpg"));

BufferedImage imgDst = trueTo256(imgSrc);

ImageIO.write(imgDst, "gif", new File("landscape-1-256.gif"));

}

}

我们对以下图像进行处理:

9188b4639a83

landscape.jpg

处理效果如下图

9188b4639a83

landscape-1-256.gif

(二)使用流行色算法实现的方法及效果

用流行色算法实现转换,大致的算法如下:

(1)准备一个长度为4096的数组,代表4096种颜色。对图中的每一个像素,取R,G,B的最高四位,拼成一个12位的整数,对应的数组元素加1。

(2)全部统计完后,就得到了这4096种颜色的使用频率。这其中,可能有一些颜色一次也没用到,即对应的数组元素为零。将这些为零的数组元素清除出去。

(3)将这剩余的数按从大到小的顺序排列,这样,前256种颜色就是用的最多的颜色,它们将作为调色板上的256种颜色。

(4)对于剩下的颜色并不是简单的丢弃,而是用前面的256种颜色中的一种来代替,代替的原则是找有最小平方误差的那个。

实现代码如下:

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import javax.imageio.ImageIO;

public class TrueTo256 {

public static int colorTransfer(int rgb) {

int r = (rgb&0x0F00000)>>20;

int g = (rgb&0x000F000)>>12;

int b = (rgb&0x00000F0)>>4;

return (r<<8|g<<4|b);

}

public static int colorRevert(int rgb) {

int r = (rgb&0x0F00)<<12;

int g = (rgb&0x000F0)<<8;

int b = (rgb&0x00000F)<<4;

return (r|g|b);

}

private static int getDouble(int a, int b) {

int red = ((a&0x0F00)>>8) - ((b&0x0F00)>>8);

int grn = ((a&0x00F0)>>4) - ((b&0x00F0)>>4);

int blu = (a&0x000F) - (b&0x000F);

return red*red + blu*blu + grn*grn;

}

public static int getSimulatorColor(int rgb, int[] rgbs, int m) {

int r = 0;

int lest = getDouble(rgb, rgbs[r]);

for (int i=1; i < m; i++) {

int d2 = getDouble(rgb, rgbs[i]);

if (lest > d2) {

lest = d2;

r = i;

}

}

return rgbs[r];

}

public static void transferTo256(int[][] rgbs) {

int n = 4096;

int m = 256;

int[] colorV = new int[n];

int[] colorIndex = new int[n];

//初始化

for (int i=0; i < n; i++) {

colorV[i] = 0;

colorIndex[i] = i;

}

//颜色转换

for (int x = 0; x < rgbs.length; x++) {

for (int y = 0; y < rgbs[x].length; y++) {

rgbs[x][y] = colorTransfer(rgbs[x][y]);

colorV[rgbs[x][y]]++;

}

}

//出现频率排序

boolean exchange;

int r;

for (int i=0; i < n; i++) {

exchange = false;

for (int j=n-2; j>=i; j--) {

if (colorV[colorIndex[j+1]] > colorV[colorIndex[j]]) {

r = colorIndex[j];

colorIndex[j] = colorIndex[j+1];

colorIndex[j+1] = r;

exchange = true;

}

}

if (!exchange) break;

}

//颜色排序位置

for (int i=0; i < n; i++) {

colorV[colorIndex[i]] = i;

}

for (int x = 0; x < rgbs.length; x++) {

for (int y = 0; y < rgbs[x].length; y++) {

if (colorV[rgbs[x][y]] >= m) {

rgbs[x][y] = colorRevert(getSimulatorColor(rgbs[x][y], colorIndex, m));

} else {

rgbs[x][y] = colorRevert(rgbs[x][y]);

}

}

}

}

public static void transferToRed(int[][] rgbs) {

for (int x = 0; x < rgbs.length; x++) {

for (int y = 0; y < rgbs[x].length; y++) {

rgbs[x][y] = rgbs[x][y]&0x00FF0000;

}

}

}

public static void transferToGreen(int[][] rgbs) {

for (int x = 0; x < rgbs.length; x++) {

for (int y = 0; y < rgbs[x].length; y++) {

rgbs[x][y] = rgbs[x][y]&0x00FF00;

}

}

}

public static void transferToBlue(int[][] rgbs) {

for (int x = 0; x < rgbs.length; x++) {

for (int y = 0; y < rgbs[x].length; y++) {

rgbs[x][y] = rgbs[x][y]&0x00FF;

}

}

}

public static BufferedImage trueTo256(BufferedImage img) {

int[][] rgbs = new int[img.getWidth()][img.getHeight()];

BufferedImage cloneImg = new BufferedImage(img.getWidth(), img.getHeight(),

BufferedImage.TYPE_INT_RGB);

for (int x=0; x < rgbs.length; x++) {

for (int y=0; y < rgbs[x].length; y++) {

rgbs[x][y] = img.getRGB(x, y);

}

}

transferTo256(rgbs);

for (int x=0; x < rgbs.length; x++) {

for (int y=0; y < rgbs[x].length; y++) {

cloneImg.setRGB(x, y, rgbs[x][y]);

}

}

return cloneImg;

}

public static void main(String[] argv) throws IOException {

BufferedImage imgSrc = ImageIO.read(new File("landscape.jpg"));

BufferedImage imgDst = trueTo256(imgSrc);

ImageIO.write(imgDst, "gif", new File("landscape-2-256.gif"));

}

}

用该算法对上面的图片进行处理,实现效果如下:

9188b4639a83

landscape-2-256.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值