1. 程式人生 > >將24位點陣圖轉換8位點陣圖

將24位點陣圖轉換8位點陣圖

bmpTest.h   :介紹BMP檔案的格式及結構定義
bmpTest.cpp : 24bitBMP顏色資料到256色點陣圖顏色資料的轉換函式實現,具體演算法可參考以 前的一個帖子
bmpTransfer.cpp  :  讀入一個24bitBMP檔案,轉換成一個256色BMP檔案的程式

編譯完成後得到的程式,如bmpTransfer.exe
執行  bmpTransfer file1 file2
file1是24bit的BMP點陣圖原始檔名,file2是新生成的256色點陣圖檔名

可以用windows畫板程式檢視結果,似乎比直接用畫板程式將24bitBMP存成256色BMP檔案的轉換效果要好哦。

bmpTest.h

/*************
   bmpTest.h
**************/
#ifndef __BMPTEST_H_
#define __BMPTEST_H_

#include <stdio.h>

typedef unsigned char  BYTE;
typedef unsigned short WORD;


// BMP影象各部分說明如下

/***********
    第一部分    點陣圖檔案頭
該結構的長度是固定的,為14個位元組,各個域的依次如下:
    2byte   :檔案型別,必須是0x4d42,即字串"BM"。
    4byte   :整個檔案大小
    4byte   :保留字,為0
    4byte   :從檔案頭到實際的點陣圖影象資料的偏移位元組數。
*************/

typedef struct
{
    long imageSize;
    long blank;
    long startPosition;
    void show(void)
    {
        printf("BMP Head:\n");
        printf("Image Size:%d\n",imageSize);
        printf("Image Data Start Position : %d\n",startPosition);
    }
}BmpHead;

/*********************
    第二部分    點陣圖資訊頭
該結構的長度也是固定的,為40個位元組,各個域的依次說明如下:
    4byte   :本結構的長度,值為40
    4byte   :影象的寬度是多少象素。
    4byte   :影象的高度是多少象素。
    2Byte   :必須是1。
    2Byte   :表示顏色時用到的位數,常用的值為1(黑白二色圖)、4(16色圖)、8(256色圖)、24(真彩色圖)。
    4byte   :指定點陣圖是否壓縮,有效值為BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS。Windows點陣圖可採用RLE4和RLE8的壓縮格式,BI_RGB表示不壓縮。
    4byte   :指定實際的點陣圖影象資料佔用的位元組數,可用以下的公式計算出來:
              影象資料 = Width' * Height * 表示每個象素顏色佔用的byte數(即顏色位數/8,24bit圖為3,256色為1)
              要注意的是:上述公式中的biWidth'必須是4的整數倍(不是biWidth,而是大於或等於biWidth的最小4的整數倍)。
              如果biCompression為BI_RGB,則該項可能為0。
    4byte   :目標裝置的水平解析度。
    4byte   :目標裝置的垂直解析度。
    4byte   :本影象實際用到的顏色數,如果該值為0,則用到的顏色數為2的(顏色位數)次冪,如顏色位數為8,2^8=256,即256色的點陣圖
    4byte   :指定本影象中重要的顏色數,如果該值為0,則認為所有的顏色都是重要的。
***********************************/
typedef struct 
{
    long    Length;
    long    width;
    long    height;
    WORD    colorPlane;
    WORD    bitColor;
    long    zipFormat; 
    long    realSize;
    long    xPels;
    long    yPels;
    long    colorUse;
    long    colorImportant;
    void show(void)
    {      
        printf("infoHead Length:%d\n",Length);
        printf("width&height:%d*%d\n",width,height);  
        printf("colorPlane:%d\n",colorPlane);
        printf("bitColor:%d\n",bitColor);
        printf("Compression Format:%d\n",zipFormat);
        printf("Image Real Size:%d\n",realSize);
        printf("Pels(X,Y):(%d,%d)\n",xPels,yPels);
        printf("colorUse:%d\n",colorUse);      
        printf("Important Color:%d\n",colorImportant);
    }
}InfoHead;

/***************************
    第三部分    調色盤結構
    對於256色BMP點陣圖,顏色位數為8,需要2^8 = 256個調色盤;
    對於24bitBMP點陣圖,各象素RGB值直接儲存在影象資料區,不需要調色盤,不存在調色盤區
    rgbBlue:   該顏色的藍色分量。
    rgbGreen:  該顏色的綠色分量。
    rgbRed:    該顏色的紅色分量。
    rgbReserved:保留值。
************************/
typedef struct
{
         BYTE   rgbBlue;
         BYTE   rgbGreen;
         BYTE   rgbRed;
         BYTE   rgbReserved;
         void show(void)
         {
            printf("Mix Plate B,G,R:%d %d %d\n",rgbBlue,rgbGreen,rgbRed); 
         }
}RGBMixPlate;

/****************************
    第四部分    影象資料區
    對於用到調色盤的點陣圖,影象資料就是該象素顏色在調色盤中的索引值;
    對於真彩色圖,影象資料就是實際的R、G、B值。
        2色圖,用1位就可以表示該象素的顏色,所以1個位元組可以表示8個象素。
        16色圖,用4位可以表示一個象素的顏色,所以1個位元組可以表示2個象素。
        256色圖,1個位元組剛好可以表示1個象素。
        真彩色圖,3個位元組才能表示1個象素。        
****************************/


//將24bit的象素顏色資料轉換為256色圖的影象資料(即索引值)
int Transfer(WORD *color24bit, int len, BYTE *Index, RGBMixPlate *mainColor);

#endif
bmpTest.cpp
/***************
    bmpTest.cpp
****************/
#include "bmpTest.h"
#include <string.h>
#include <assert.h>

//計算平方差的函式
int PFC(int color1, int color2)
{
    int x,y,z;
    x = (color1 & 0xf) - (color2 & 0xf);
    y = ((color1>>4) & 0xf) - ((color2>>4) & 0xf);
    z = ((color1>>8) & 0xf) - ((color2>>8) & 0xf);
    return (x*x + y*y + z*z);
};

//直接插入排序
int Sort1(int *src, int *attach, int n)
{
    int cur, cur1;
    int i,j,k=0;
    for (i = 1; i < n; i++)
    {
        cur     = src[i];
        cur1 = attach[i];
        for (j = i - 1; j >= 0; j--)
        {
            if (cur > src[j])
            {
                src[j+1]    = src[j];
                attach[j+1] = attach[j];
            }
            else
                break;
        }
        src[j+1]  = cur;
        attach[j+1] = cur1;
    }
    return 0;
}

//快速排序
int Sort2(int *src, int *attach, int n)
{
    if (n <= 12)
        return Sort1(src, attach, n);
    int low = 1, high = n - 1;
    int tmp;
    while (low <= high)
    {
        while (src[low] >= src[0])
        {
            if (++low > n - 1)
                break;
        }
        while (src[high] < src[0])
        {
            if (--high < 1)
                break;
        }
        if (low > high)
            break;
        {
            tmp                = src[low];
            src[low]        = src[high];
            src[high]        = tmp;
            tmp                = attach[low];
            attach[low]        = attach[high];
            attach[high]    = tmp;
        }
        low++;
        high--;
    }

    
    {
        tmp                = src[low - 1];
        src[low - 1]    = src[0];
        src[0]            = tmp;
        tmp                = attach[low - 1];
        attach[low - 1]    = attach[0];
        attach[0]        = tmp;
    }
    if (low > 1)
        Sort2(src, attach, low - 1);
    if (low < n)
        Sort2(&src[low], &attach[low], n - low);
    return 0;
}

//將24bit的象素顏色資料轉換為256色圖的影象資料(即索引值)
int Transfer(WORD *color24bit, int len, BYTE *Index, RGBMixPlate *mainColor)
{
    int usedTimes[4096] = {0};
    int miniColor[4096];
    for (int i = 0; i < 4096; i++)
        miniColor[i] = i;
    i = 0;
    for (i = 0; i < len; i++)
    {
        assert(color24bit[i] < 4096);
        usedTimes[color24bit[i]]++;
    }

    int numberOfColors = 0;
    for (i = 0; i < 4096; i++)
    {
        if (usedTimes[i] > 0)
            numberOfColors++;
    }

    //對usedTimes進行排序,排序過程中minColor陣列(儲存了顏色值)也作與useTimes
    //陣列相似的交換
    Sort2(usedTimes, miniColor, 4096);

    //usedTimes陣列中是各顏色使用頻率,從高到低排列,顯然第numberOfColor個之後的都為0
    //miniColor陣列中是相應的顏色資料
    //將前256個顏色資料儲存到256色點陣圖的調色盤中
    for (i = 0; i < 256; i++)
    {
        mainColor[i].rgbBlue    = (BYTE)((miniColor[i]>>8)<<4);
        mainColor[i].rgbGreen    = (BYTE)(((miniColor[i]>>4) & 0xf)<<4);
        mainColor[i].rgbRed        = (BYTE)((miniColor[i] & 0xf)<<4);
        mainColor[i].rgbReserved = 0;
    }

    int *colorIndex = usedTimes;//用原來的useTimes陣列來儲存索引值
    memset(colorIndex, 0, sizeof(int) * 4096);
    
    if (numberOfColors <= 256)
    {
        for (i = 0; i < numberOfColors; i++)
            colorIndex[miniColor[i]] = i;
    }
    else//為第256之後的顏色在前256種顏色中找一個最接近的
    {
        for (i = 0; i < 256; i++)
            colorIndex[miniColor[i]] = i;
        
        int index, tmp, tmp1;
        for (i = 256; i < numberOfColors; i++)
        {
            tmp      = PFC(miniColor[0], miniColor[i]);
            index = 0;
            for (int j = 1; j < 256; j++)
            {
                tmp1 = PFC(miniColor[j], miniColor[i]);
                if (tmp > tmp1)
                {
                    tmp = tmp1;
                    index = j;
                }
            }
            colorIndex[miniColor[i]] = index;
        }
    }
    //記錄各點顏色資料的索引值,即256色點陣圖的顏色資料
    for (i = 0; i < len; i++)
    {
        assert(colorIndex[color24bit[i]] < 256);
        Index[i] = colorIndex[color24bit[i]];
    }

    return 1;      
}



bmpTransfer.cpp
/********************
  bmpTransfer.cpp
********************/
#include "bmpTest.h"
#include <string.h>

int __cdecl main(int argc,char* argv[])
{
    if (argc < 3)
    {
        printf("Usage:\n");
        printf("    %s filename1 filename2\n", argv[0]);
        printf("    filename1 : source 24bit BMP filename    like: xxx.bmp\n");
        printf("    filename2 : new 256 color BMP filename\n");
        return -1;
    }
    BmpHead  headBMP;
    InfoHead infoHead; 
    FILE* p;
    char* filename = argv[1];
    p = fopen(filename,"rb");
    if (p == NULL)
    {
        printf("!!!file %s open failed.\n", filename);
    }

    printf("file %s open success.\n",filename); 
/**********   read BMP head ********************/                
    fseek(p,2,SEEK_CUR);
    fread(&headBMP,1,12,p);
    headBMP.show();
    fread(&infoHead,1,40,p);
    infoHead.show();
    if (infoHead.bitColor != 24)
    {
        fclose(p);
        printf("This is not a 24bit BMP file.\n");
        return -1;
    }
/***********  read Image Date  **************/
    long nData = infoHead.realSize;
    BYTE* pColorData = new BYTE[nData];
    fread(pColorData,1,nData,p);
    printf("last 4 byte of color Data:%x %x %x %x\n",\
        pColorData[nData-4],pColorData[nData-3],\
        pColorData[nData-2],pColorData[nData-1]);

/***********  read file over ***************/
    int leftData = 0;
    char ch = 0;
    while (!feof(p))
    {
        fread(&ch,1,1,p);
        leftData++;
    }
    if (leftData)
        printf("%d bytes not read in file.\n", leftData);
    printf("read file over.\n");   
    if(!fclose(p))
    {
        printf("file close.\n");
    }
// 24位BMP檔案資訊都讀出來了,可以檢視列印資訊

/************  24bit到256色的顏色資料轉換  *****************/
    BYTE* Index = new BYTE[nData/3];
    RGBMixPlate  mainColor[256];
    memset(mainColor, 0, sizeof(mainColor));
    WORD* shortColor = new WORD[nData/3];
    int iRed, iGreen, iBlue;
    for (int i = 0; i < nData/3; i++)
    {//取RGB顏色的高4位
        iRed    = pColorData[i*3]>>4;
        iGreen    = pColorData[i*3+1]>>4;
        iBlue    = pColorData[i*3+2]>>4;
        shortColor[i] = (iRed<<8) + (iGreen<<4) + iBlue;
    }
    delete []pColorData;
    //呼叫轉換函式
    Transfer(shortColor, nData/3, Index, mainColor);

    delete []shortColor;  
//轉換完成,256色點陣圖的調色盤資料(儲存在mainColor)和影象資料區的資料(儲存在Index中)

/************  寫一個新的256色BMP檔案  *******************/
     
//修改一下前面讀出的BmpHead和InfoHead的結構資訊
    headBMP.imageSize = 14 + 40 + 4*256 + nData/3;    
                    // 4*256是調色盤的長度,nData/3是影象資料區長度
    headBMP.startPosition += 4*256;     //新檔案加上了調色盤部分
    infoHead.bitColor = 8;              //顏色位數改為8
    infoHead.realSize = nData/3;        //影象資料區長度
        
//寫新檔案
    char* newFile = argv[2];
    FILE *p1 = fopen(newFile,"wb");
    if (NULL == p1)
    {
        printf("open new file failed.\n");
        return -1;
    }
    char hh[2] = {0x42, 0x4D};
    fwrite(hh,1,2,p1);                //BMP檔案開頭兩位元組, 0x4d42 = "BM"
    fwrite(&headBMP, 1, 12, p1);    //BMP檔案頭 
    fwrite(&infoHead, 1, 40, p1);    //BMP檔案頭資訊 
    fwrite(mainColor, 1, sizeof(mainColor), p1);//寫調色盤資訊
    fwrite(Index, 1, nData/3, p1);  //顏色資料
    fclose(p1);

    //釋放分配的記憶體
    delete []Index;
    return 0;
}


相關推薦

24點陣轉換8點陣

bmpTest.h   :介紹BMP檔案的格式及結構定義 bmpTest.cpp : 24bitBMP顏色資料到256色點陣圖顏色資料的轉換函式實現,具體演算法可參考以 前的一個帖子 bmpTransfer.cpp  :  讀入一個24bitBMP檔案,轉換成一個256色B

bmp點陣檔案:讀取、寫入、24真彩轉8灰度、灰度的二值化

影象的二值化處理就是講影象上的點的灰度置為0或255,也就是講整個影象呈現出明顯的黑白效果。即將256個亮度等級的灰度影象通過適當的閥值選取而獲得仍然可以反映影象整體和區域性特徵的二值化影象。在數字影象處理中,二值影象佔有非常重要的地位,特別是在實用的影象處理中,以二值影象處理實現而構成的系統是很多的,要進行

24點陣8灰度

如何用RGB轉化得到的灰度資料寫入8位bmp檔案,請看如下程式碼 其中lp中儲存的是已經轉化得到的現成灰度資料,標紅的程式碼是與24位點陣圖不同的地方。 <span style="font-size:18px;">//(整個點陣圖由檔案頭、資訊頭、調色盤、顏色

C# 指標法24點陣8

用指標操作,將24位的彩色影象轉換位8位的灰度圖 試了速度是9ms,比之前的那種方法快了很多。   注意unsafe,勾選允許不安全的程式碼。 using System; using System.Collections.Generic; using System.Com

c# byte陣列轉換 8有符號整數 16有符號整數 32有符號整數

   byte陣列   byte[] aa = new byte[] { 0xF8, 0x66, 0x55, 0x44 }; 1.轉換成8位有符號整數   sbyte sb = (sbyte)aa[0]; 2.轉換成16位有符號整數 &n

GPIOA高8輸入控制低8輸出(運算)

1、位操作 int main() { //高8位浮空輸入,低8位推輓輸出 GPIOA->CRH = 0x44444444; GPIOA->CRL = 0x

Android獲取資料時 浮點型整數數值(超8)過大導致科學計數法

今天在調介面時,有個實體變數A我定義float型別,當該變數的整數值超過8位的時候會出現科學計數法的情況 例如 19085161.59,顯示成1.454654864E的情況本來可以用String型別接收該欄位,但由於需要該數值做運算,所以想不改變原有型別一開始想過顯示時通過 

C# 圖片深度轉至8灰度影象,8灰度影象轉為1灰度影象

        #region 二值化         #region Otsu閾值法二值化模組            /// <summary>            /// Otsu閾值            /// </summary>  

GPIOA高8輸入控制低8輸出(暫存器操作)

int main() { GPIOA->CRH = 0x44444444; GPIOA->CRL = 0x33333333; while(1) {

opengl全景轉換為天空盒(成功)

前面哪個opengl程式實際上已經快成功了,只差一點點了。發現只要前、後圖對換,左、右圖對換就可以了所以這裡除了對換外,把哪個要按2次鍵才能截到正確的圖也改一下(延時)具體看程式碼吧://53 全景球貼圖 切分6圖 //左鍵(+ 移動)旋轉,右鍵(+ 移動)縮放 1

【數字影象】C++824BMP點陣的平滑、銳化、二值化處理,以及24真彩圖的灰度化

BMP標頭檔案: #ifndef BMP_H//前處理器 #define BMP_H typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef

24點陣轉成8灰度點陣

24位轉8位灰度比較簡單,先設定調色盤,如下樣子 (0,0,0,0)(1,1,1,0)(2,2,2,0)……一共256個,用公式gray = (0.114*Blue+0.587*Green+0.299*Red)得到的gray為該畫素點在8位點陣圖中調色盤的索引,所以,只要把2

MATLAB讀取黑白像顯示卻是黑色,24深轉8深黑白像解決方法

com 問題 欺騙 alt width 圖. 如果 技術分享 src 1、24位深轉8位深: ps將24位深原圖.png保存為GIF圖256即為8位,再將8位gif圖轉為需要的.png,即轉為8位深png圖。 2、MATLAB讀取黑白圖像顯示幾乎全為黑色: 這是最近處理圖像

arm 常數必須對應8 點陣,即常數是由一個8 的常數迴圈移位偶數得到

在ARM指令集彙編碼碼中,32位有效立即數是通過 偶數位而間接得到的 在12位的shifter_operand中:8位存資料,4位存移位的次數。8位存資料:解釋了“該常數必須對應8位點陣圖”。 4位存移位的次數:解釋了為什麼只能移偶數位。4位只有16種可能值,而32位數可以迴圈移位32次(3

Python8的圖片轉為24的圖片

用的pytorch來訓練deeplabv3+ 在做deeplabv3+的過程中,我的訓練圖片是8位的,如下圖: 8位的: 24位的: 這樣雖然在訓練過程中能夠正常訓練。但是在評估過程中會出錯,所以決定將訓練圖片轉成24點陣圖,重新訓練。最後結果也表明了,只要

Java實現24真彩轉換8灰度圖片

         Windows下的點陣圖檔案即我們通常所熟悉的BMP圖片,其儲存結構的格式可以在WINGDI.h檔案中找到定義。BMP檔案大體上分為四個部分: 1.      點陣圖檔案頭(BITMAPFILEHEADER) 2.      點陣圖資訊頭(BITMAPIN

使用GDI+實現24 點陣轉32點陣

  今天利用修改影象的alpha通道實現了影象的倒影,但是在對影象進行測試的時候,發現24位的點陣圖不能實現倒影,究其原因是24位以下的影象沒有alpha通道,也就沒辦法利用修改alpha通道的方式去實現影象的倒影。於是就想辦法實現24點陣圖像轉成32點陣圖像。也就能具有al

24點陣轉4彩色(BMP)

之前的“24位點陣圖轉4位灰度圖”中已經說明了,調色盤與圖象資料格式。 這裡對圖象資料格式做下補充,並講解24位點陣圖轉4位彩色圖的演算法 1.圖象資料格式 在我完成這個演算法的編碼時,執行效果有一個非常嚴重的錯誤,就是所有的藍和紅色反了。也就是說,應該是藍色的地方呈現了紅色,應該是紅色的地方呈現了蘭色。

用棧實現十進位制數轉換為任意進制數(2,8,16...).

解題思路:假如N為輸入的數,n為要轉換為的進位制,若要將十進位制231轉換為8進位制數,過程如下; N                        N/n                      N%n 231                   28