九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
降低顏色深度及調(diào)色板處理

降低顏色深度及調(diào)色板處理

Posted on 2012-06-05 18:24 assassinx 閱讀(863) 評(píng)論(0) 編輯 收藏

上一次講到哪了,說(shuō)了下bmp位圖格式以及圖像處理入門。門也入了 搞點(diǎn)別的吧,好 我們繼續(xù)接著折騰。bmp格式的數(shù)據(jù)就放在內(nèi)存里 你愛(ài)折騰不折騰他就在那
總之一句話 搞清楚他的結(jié)構(gòu) 用你清晰的邏輯去處理它。
我們這次要做的事情是降低顏色深度及調(diào)色板處理,反正我是找了園子里也沒(méi)看見(jiàn)類似的東西 都是C++或者其他什么的??傊覀円龅倪@兩個(gè)事情都要用到調(diào)色板。
要想取得一個(gè)圖像的調(diào)色板的所有顏色I(xiàn)mage.Palette.Entries 就可以了 得到的是一個(gè)Color數(shù)組。有些固定顏色深度的圖像 都有默認(rèn)的調(diào)色板比如4位(16色)8位(256色)等。 你用過(guò)win31 或者win95沒(méi)裝顯卡驅(qū)動(dòng)時(shí)一定見(jiàn)過(guò)那些豬肝色的圖像 。我們初始化一個(gè)4位的bmp圖像(16色)來(lái)看看他默認(rèn)的調(diào)色板都有哪些顏色,添加一個(gè)叫“顏色樣本”的按鈕 這是他的代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//顯示windows默認(rèn)顏色樣本
void makeColor()
{
    Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format4bppIndexed);
    Color[] colors = bmp.Palette.Entries;
    Graphics gph = Graphics.FromHwnd(this.Handle);
    int j = 0;
    for (int i = 0; i < 4; i++)
    {
        for (int k = 0; k < 4; k++)
        {
 
            gph.FillRectangle(new SolidBrush(colors[j]), new Rectangle(new Point(k * 100,
                i * 100), new Size(100, 100)));
 
            gph.DrawString(colors[j].ToArgb().ToString("X").Substring(2),
                new Font(new FontFamily("黑體"), 15),
 
                Brushes.Lavender, new Point(k * 100, i * 100));
            j++;
        }
 
    }
 
    bmp.Dispose();
}

 
顏色表有了(就是上面代碼里抓出來(lái)的顏色表),然后是怎樣讓每個(gè)像素的顏色去根據(jù)調(diào)色板匹配最近似的顏色呢 http://dev.gameres.com/Program/Visual/Other/256color.htm  這是一個(gè)C++的實(shí)現(xiàn) 不過(guò)我沒(méi)看懂 - -! 用了另外一種傻瓜的方式去實(shí)現(xiàn),添加一個(gè)名為“調(diào)色板算法”的按鈕 這是他的代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//256色調(diào)色板的匹配處理 http://dev.gameres.com/Program/Visual/Other/256color.htm
//沒(méi)看懂不過(guò)我實(shí)現(xiàn)了他的另外一個(gè)效率很低的算法
//調(diào)色板匹配/降低顏色深度的 算法 效率有點(diǎn)低 原理是對(duì)的
//出來(lái)的結(jié)果跟畫(huà)圖板另存為16色 是一模一樣的 要256色同理                
void tranTo16()
{
    Bitmap img = (Bitmap)Bitmap.FromFile("mm.bmp");
 
    //準(zhǔn)備調(diào)色板 這個(gè)是從畫(huà)圖板新建16色位圖文件里抓出來(lái)的
    Color[] colors = new Color[16];
    colors[0] = Color.FromArgb(0x00, 0x00, 0x00);
    colors[1] = Color.FromArgb(0x80, 0x00, 0x00);
    colors[2] = Color.FromArgb(0x00, 0x80, 0x00);
    colors[3] = Color.FromArgb(0x80, 0x80, 0x00);
    colors[4] = Color.FromArgb(0x00, 0x00, 0x80);
    colors[5] = Color.FromArgb(0x80, 0x00, 0x80);
    colors[6] = Color.FromArgb(0x00, 0x80, 0x80);
    colors[7] = Color.FromArgb(0x80, 0x80, 0x80);
    colors[8] = Color.FromArgb(0xc0, 0xc0, 0xc0);
    colors[9] = Color.FromArgb(0xff, 0x00, 0x00);
    colors[10] = Color.FromArgb(0x00, 0xff, 0x00);
    colors[11] = Color.FromArgb(0xff, 0xff, 0x00);
    colors[12] = Color.FromArgb(0x00, 0x00, 0xff);
    colors[13] = Color.FromArgb(0xff, 0x00, 0xff);
    colors[14] = Color.FromArgb(0x00, 0xff, 0xff);
    colors[15] = Color.FromArgb(0xff, 0xff, 0xff);
 
    Graphics gph = Graphics.FromHwnd(this.Handle);
 
    int tmp;
    for (int i = 0; i < img.Height; i++)
    {
        for (int j = 0; j < img.Width; j++)
        {
            tmp = 255 * 3;
            Color tmpCol = Color.FromArgb(255, 255, 255);
            for (int k = 0; k < colors.Length; k++)
            {
                Color src = colors[k];
                Color des = img.GetPixel(j, i);
                //原理就是檢查每個(gè)像素的rgb跟調(diào)色板中的比較 選中差值最小的那個(gè),那么就一定是"最相近"的顏色了
                int val = Math.Abs(des.R - src.R) + Math.Abs(des.G - src.G) + Math.Abs(des.B - src.B);
 
                if (val < tmp)
                {
                    tmp = val;
                    tmpCol = src;
                }
 
            }
 
            img.SetPixel(j, i, tmpCol);
        }
    }
 
 
    gph.DrawImage(img, new Point(0, 0));
    gph.Dispose();
    img.Dispose();
}

怎么樣試下吧 用畫(huà)圖板轉(zhuǎn)存為16色位圖 看下是不是跟他是一模一樣的,說(shuō)明咱的方法是對(duì)的 要的就是這個(gè)效果。  看下這個(gè)圖像的畫(huà)面真的慘不忍睹啊

有時(shí)候win95下有些很神奇的程序他們用4位的模式竟然也可以顯示出不算太差的圖像(抖動(dòng)算法 這個(gè)俺還不會(huì) ╮(╯﹏╰)╭)
有沒(méi)有既稍微保留畫(huà)面質(zhì)量又降低數(shù)據(jù)量的方法呢。有啊 改調(diào)色板不就得了嘛 讓調(diào)色板的顏色盡量跟畫(huà)面整體匹配,上面說(shuō)了取得調(diào)色板跟調(diào)色板里的顏色都很簡(jiǎn)單Image.Palette 但是試了就知道通過(guò)給調(diào)色板的顏色賦值 或者直接更改調(diào)色板根本都不起作用的,如果有哪位哥們兒知道 告訴我下。參考上一篇第一個(gè)例子 我們知道 這個(gè)得用非常手段 根據(jù)格式直接對(duì)bmp內(nèi)存數(shù)據(jù)進(jìn)行操作,本文只討論方法這里就不寫(xiě)調(diào)色板操作的代碼了,通過(guò)一段偷懶的代碼見(jiàn)證他的可行性。把對(duì)colors數(shù)組賦值的16行改成這樣:

1
2
3
4
Random rdm = new Random();
for (int i = 0; i < colors.Length; i++)
    colors[i] = img.GetPixel(rdm.Next(0,
        img.Width - 1), rdm.Next(0, img.Height - 1));

 

這個(gè)圖像像是16色的圖像嗎 不會(huì)吧再怎么看著也比16色好很多啊,怎么樣調(diào)色板的神奇之處 瞬間圖像質(zhì)量就有很大提升吧。你可以寫(xiě)更好的算法對(duì)圖像的色調(diào)進(jìn)行分析生成更智能的調(diào)色板  以前的老游戲由于發(fā)色數(shù)有限 調(diào)色板應(yīng)用非常廣泛。

該結(jié)尾了我們來(lái)實(shí)際寫(xiě)個(gè)24位真彩色bmp圖像轉(zhuǎn)8位256色的例子,添加一個(gè)叫“降低顏色深度”的按鈕 這是對(duì)應(yīng)的代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
void tranTo256()
{
    Bitmap srcImg = new Bitmap("mm.bmp");
 
    Bitmap desImg = new Bitmap(srcImg.Width, srcImg.Height, PixelFormat.Format8bppIndexed);
    MemoryStream desImgData = new MemoryStream();
    desImg.Save(desImgData, ImageFormat.Bmp);
    Color[] pal = desImg.Palette.Entries;
    BitmapData data = srcImg.LockBits(new Rectangle(0, 0, srcImg.Width, srcImg.Height),
        ImageLockMode.ReadWrite, srcImg.PixelFormat);
     
    unsafe
    {
        byte* ptr = (byte*)data.Scan0;
        int tmp;
        //掃描的時(shí)候是由上到下,存儲(chǔ)的時(shí)候是由下到上
        for (int i =0 ; i <srcImg.Height  ; i++)//(int i = srcImg.Height - 1; i > 0; i--)
        {
            int offSet = data.Stride * i;
            for (int j = 0; j < srcImg.Width * 3; j += 3)
            {
                tmp = 255 * 3;
                byte palIndx = 0;
 
                for (int k = 0; k < pal.Length; k++)
                {
                    Color src = pal[k];
                    Color des = Color.FromArgb(ptr[offSet + j + 2], ptr[offSet + j + 1], ptr[offSet + j]);
                    int val = Math.Abs(des.R - src.R) + Math.Abs(des.G - src.G) + Math.Abs(des.B - src.B);
 
                    if (val < tmp)
                    {
                        tmp = val;
                        palIndx = (byte)k;
                    }
 
                }
                desImgData.WriteByte(palIndx);
            }
             
        }
    }
    desImg = (Bitmap)Bitmap.FromStream(desImgData);
    srcImg.UnlockBits(data);
    Graphics.FromHwnd(this.Handle).DrawImage(desImg, new Point(0, 0));
 
    desImg.Save("gs.bmp");
    desImgData.Close();
    srcImg.Dispose();
    desImg.Dispose();
}

貌似什么都對(duì)的就是出不來(lái)呢 一個(gè)純黑背景的圖片,因?yàn)閷?xiě)數(shù)據(jù)之前游標(biāo)沒(méi)有到達(dá)指定位置 在unsafe前面加上這句就ok了:

1
desImgData.Seek(54 + 256 * 4, SeekOrigin.Begin);//數(shù)據(jù)開(kāi)始位置,參考位圖文件格式說(shuō)明

 看下效果吧:

哇 怎么回事倒了 怎么會(huì)倒了呢 看見(jiàn)咱代碼里注釋的提示了沒(méi) //掃描的時(shí)候是由上到下,存儲(chǔ)的時(shí)候是由下到上
原理不多說(shuō) ,把外層for循環(huán)圓括號(hào)里部分用注釋的那段替換就行了
這就沒(méi)問(wèn)題了  真的么 真的就沒(méi)問(wèn)題了嗎
用畫(huà)圖板打開(kāi)bin目錄那個(gè)叫"mm.bmp"圖像 ,然后 單擊“圖像”菜單->屬性 現(xiàn)在寬度是不是400 ,請(qǐng)改成399 按ctr+s保存
然后再運(yùn)行程序:

為什么400可以399就不行呢。又涉及4倍字節(jié)數(shù)這個(gè)扯淡的問(wèn)題。
我們像素寬是400對(duì)吧 8位256色 一個(gè)像素一個(gè)字節(jié) 對(duì)吧 正好400字節(jié) 能被4整除
如果399像素 就需要補(bǔ)齊一個(gè)字節(jié) 在最外層循環(huán)加上這句就ok了:

1
desImgData.WriteByte(0x00);

 不行 咱得讓他更智能點(diǎn) 把剛剛那段代碼替換成這段:

1
2
3
4
5
6
int fill = ((srcImg.Width * 8 + 31) / 32 * 4) - srcImg.Width;
if (fill > 0)
{
    byte[] fills = new byte[fill];
    desImgData.Write(fills, 0, fills.Length);
}

 好了折騰夠了 大功告成,對(duì)應(yīng)目錄已經(jīng)生成了一個(gè)8位名字“gs.bmp”的位圖。 有些部分沒(méi)完善只起到拋磚引玉的作用 見(jiàn)諒 自己去搞:

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
BMP文件存儲(chǔ)結(jié)構(gòu)的格式
BMP讀取(一)
BMP文件格式詳解(BMP file format)
BMP
J2ME插值算法實(shí)現(xiàn)圖片的放大縮小 - JAVA、J2ME - Android開(kāi)發(fā)基礎(chǔ) -...
phoshop 技能大全 色彩技巧
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服