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"));
}
}
我們對以下圖像進行處理:
landscape.jpg
處理效果如下圖
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"));
}
}
用該算法對上面的圖片進行處理,實現效果如下:
landscape-2-256.gif
總結
以上是生活随笔為你收集整理的java彩色的世界_JAVA真彩色转256色的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 联想集团第二季度营收 144.1 亿美元
- 下一篇: map原理 java_RxJava的基本