程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> 圖像處理-用C語言將bmp 8位灰度圖的灰度值縮小16倍,調色板中數值由255行變成16行調

圖像處理-用C語言將bmp 8位灰度圖的灰度值縮小16倍,調色板中數值由255行變成16行調

編輯:編程綜合問答
用C語言將bmp 8位灰度圖的灰度值縮小16倍,調色板中數值由255行變成16行調

用C語言將bmp 8位灰度圖的灰度值縮小16倍,由0-255變成0-16,調色板中數值由255行變成16行,同時調色板rgbBlue rgbRed rgbGreen數值范圍由0-255變成0-1。我用c語言實現後,為什麼圖片不再是灰度圖,有了其他顏色???

```#pragma once
#ifndef BMP_H_INCLUDED
#define BMP_H_INCLUDED
#include
#include
#include
#include
#include
#include
typedef unsigned short WORD;//2字節
typedef unsigned long DWORD;//4字節
typedef long LONG;
typedef unsigned char BYTE;
#define pi 3.1415926535

/* 位圖文件頭結構 14字節 */
typedef struct tagBITMAPFILEHEADER
{ // bmfh
WORD bfType;//位圖文件類型,必須為BMP(0-1字節)
DWORD bfSize;//位圖文件大小,以字節為單位(2-5字節)
WORD bfReserved1;//位圖文件保留字,必須為0(6-7字節)
WORD bfReserved2;//位圖文件保留字,必須為0(8-9字節)
DWORD bfOffBits;//位圖數據的起始位置,以相對於位圖文件頭的偏移量表示(10-13字節)
}BITMAPFILEHEADER;

/* 位圖信息頭結構 40字節 */
typedef struct tagBITMAPINFOHEADER
{ // bmih
DWORD biSize; // 本結構占得字節數(14-17字節),結構長度 40B
LONG biWidth;//位圖的寬度,以像素為單位(18-21字節)
LONG biHeight;//位圖的高度,以像素為單位(22-25字節)
WORD biPlanes;//顏色面板值必須為1(26-27字節)
WORD biBitCount;// 表示顏色要用到的位數,顏色位值可以是1(雙色),(28-29字節)
//4(16色),8(256色),16(64K色,高彩色),24(16M,真彩色),32(4096M增強型真彩色)中的一個
DWORD biCompression;// 壓縮格式,必須是0(不壓縮)(30-33字節)
//1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)或3(Bitfields,位域存放)
DWORD biSizeImage;// 位圖的大小,位圖占用字節數=biWidth(4的整倍數)*biHeight
LONG biXPelsPerMeter;// 水平分辨率,每米像素數(38-41字節)
LONG biYPelsPerMeter;// 垂直分辨率,每米像素數(42-45字節)
DWORD biClrUsed;// 位圖實際使用的顏色表中的顏色數,(46-49字節)
DWORD biClrImportant;// 位圖顯示過程中重要的顏色數(50-53字節)
}BITMAPINFOHEADER;

/* 調色板 4字節 */
//顏色表中RGBQUAD結構數據的個數由biBitCount來確定
//顏色表中RGBQUAD結構數據的個數有biBitCount來確定:
// 當biBitCount=1,4,8時,分別有2,16,256個表項;????????????
// 當biBitCount=24時,沒有顏色表項
typedef struct tagRGBQUAD
{ // rgbq
double rgbBlue;//藍色的亮度(值得范圍0-255)
double rgbGreen;//綠色的亮度
double rgbRed;//紅色的亮度
double rgbReserved;//保留,必須為0
}RGBQUAD;

//位圖數據
//位圖數據記錄了位圖的每一個像素值,記錄順序是在掃描行內是從左到右,
//掃描行之間是從下到上。位圖的一個像素值所占的字節數:
/* 當biBitCount=1時,8個像素占1個字節;
  當biBitCount=4時,2個像素占1個字節;
  當biBitCount=8時,1個像素占1個字節;
  當biBitCount=24時,1個像素占3個字節;*/
//Windows規定一個掃描行所占的字節數必須是4的倍數(即以long為單位),不足的以0填充,
/* 定義圖像信息 */
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;//位圖信息頭
RGBQUAD bmiColors[1];//顏色表
}BITMAPINFO;

/* 定義位圖圖像 /
typedef struct _Bitmap
{
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
int width;
int height;
int bitCount; // 8 或者24
int imageSize; // 圖像數據大小(imageSize=height*widthStep)字節
BYTE
imageData; //排列的圖像數據,指向存儲空間第一個單元的
int widthStep; //排列的圖像行大小,不夠4的整數倍的就補0
}Bitmap;

/**

  • 位圖創建函數 創建一個Bitmap結構,並為圖像數據分配空間 *
  • 使用方法:
  • Bitmap bmp=(Bitmap)malloc(sizeof(Bitmap));
  • ret=CreateBitmap(bmp,50,50,3);
    

    /
    int CreateBitmap(Bitmap
    bmp, int width, int height, int bitCount)
    {
    bmp->width = width;
    bmp->height = height;
    bmp->bmih.biWidth = width;
    bmp->bmih.biHeight = height;

    bmp->widthStep = (int)((width*bitCount + 31) / 32) * 4; //可是為什麼這樣計算????????????
    //eg:5*5的灰度圖像,bitcount=8,則計算出來,widthstep=8,一行的像素個數不夠4的倍數的補0
    bmp->imageSize = bmp->height*bmp->widthStep*sizeof(BYTE);//計算排列的圖像大小sizeof(BYTE)=1

    if (bitCount == 8)
    {
    bmp->bitCount = 8;
    bmp->bmfh.bfType = 0x4d42; //注意是4d42 這個地方折磨我一下午啊
    bmp->bmfh.bfReserved1 = 0;
    bmp->bmfh.bfReserved2 = 0;
    bmp->bmih.biBitCount = 8;
    bmp->bmih.biSize = 40;
    bmp->bmih.biPlanes = 1;
    bmp->bmfh.bfSize = 54 + 256 * 4 + height*bmp->widthStep;
    bmp->bmfh.bfOffBits = 1078;
    bmp->bmih.biBitCount = 8;
    bmp->bmih.biCompression = 0;
    bmp->bmih.biSizeImage = bmp->imageSize;
    bmp->bmih.biClrUsed = 0;
    bmp->bmih.biClrImportant = 0;
    bmp->bmih.biXPelsPerMeter = 0;
    bmp->bmih.biYPelsPerMeter = 0;
    }
    else if (bitCount == 24)
    {
    bmp->bitCount = 24;
    bmp->bmfh.bfType = 0x4d42;
    bmp->bmih.biBitCount = 24;
    bmp->bmfh.bfReserved1 = 0;
    bmp->bmfh.bfReserved2 = 0;
    bmp->bmih.biSize = 40;
    bmp->bmih.biPlanes = 1;
    bmp->bmfh.bfSize = 54 + height*bmp->widthStep;
    bmp->bmfh.bfOffBits = 54;
    bmp->bmih.biBitCount = 24;
    bmp->bmih.biSizeImage = bmp->imageSize;
    bmp->bmih.biClrUsed = 0;
    bmp->bmih.biCompression = 0;
    bmp->bmih.biClrImportant = 0;
    bmp->bmih.biXPelsPerMeter = 0;
    bmp->bmih.biYPelsPerMeter = 0;
    }
    else
    {
    printf("Error(CreateBitmap): only supported 8 or 24 bits bitmap.\n");
    return -1;
    }

    bmp->imageData = (BYTE*)malloc(bmp->imageSize); //分配數據空間
    if (!(bmp->imageData))
    {
    printf("Error(CreateBitmap): can not allocate bitmap memory.\n");
    return -1;
    }
    return 0;
    }

/**

  • 位圖指針釋放函數 釋放位圖數據空間 *
  • 使用方法:
  • ReleaseBitmap(bmp); / void ReleaseBitmap(Bitmap bmp) { free(bmp->imageData); bmp->imageData = NULL; free(bmp); bmp = NULL; }

/**

  • 路徑檢查函數:是否為BMP文件,是否可讀
  • 正確返回0,錯誤返回-1 *
  • 使用方法
  •     ret=CheckPath(path);
    

    */
    int CheckPath(char *path)
    {
    FILE *fd;
    int len = strlen(path) / sizeof(char);
    char ext[3];
    //check whether the path include the characters "bmp" at end
    strncpy(ext, &path[len - 3], 3);
    if (!(ext[0] == 'b' && ext[1] == 'm' && ext[2] == 'p')) {
    printf("Error(CheckPath): the extension of the file is not bmp.\n");
    return -1;
    }

    //check whether the file can be read or not
    fd = fopen(path, "r");
    if (!fd)
    {
    printf("Error(CheckPath): can not open the file.\n");
    return -1;
    }
    fclose(fd);

    return 0;
    }

void ShowImage(char * filepath)
{
char cmd[266];
strcpy(cmd, "start ");
strcat(cmd, filepath);
printf("%s\n", cmd);
system(cmd);
}
/**

  • 從文件中讀取位圖函數
  • 正確返回0,錯誤返回-1 *
  • 使用方法:
  • bmp=(Bitmap*)malloc(sizeof(Bitmap));
  • ret=ReadBitmap(path, bmp);
    

    /
    int ReadBitmap(char
    path, Bitmap* bmp)
    {
    int ret;
    FILE *fd;

    //檢查路徑是否可讀
    ret = CheckPath(path);
    if (ret == -1)
    {
    printf("Error(ReadRGBBitmap): the path of the image is invalid.\n");
    return -1;
    }

    ShowImage(path);
    //打開文件
    fd = fopen(path, "rb");
    if (fd == 0)
    {
    printf("Error(ReadRGBBitmap): can not open the image.\n");
    return -1;
    }
    //讀取文件信息頭14字節
    fread(&(bmp->bmfh.bfType), sizeof(WORD), 1, fd);
    fread(&(bmp->bmfh.bfSize), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmfh.bfReserved1), sizeof(WORD), 1, fd);
    fread(&(bmp->bmfh.bfReserved2), sizeof(WORD), 1, fd);
    fread(&(bmp->bmfh.bfOffBits), sizeof(DWORD), 1, fd);

    //讀取位圖信息頭40字節
    fread(&(bmp->bmih.biSize), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biWidth), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biHeight), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biPlanes), sizeof(WORD), 1, fd);
    fread(&(bmp->bmih.biBitCount), sizeof(WORD), 1, fd);
    fread(&(bmp->bmih.biCompression), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biSizeImage), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biXPelsPerMeter), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biYPelsPerMeter), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biClrUsed), sizeof(DWORD), 1, fd);
    fread(&(bmp->bmih.biClrImportant), sizeof(DWORD), 1, fd);

    //創建位圖結構
    ret = CreateBitmap(bmp, bmp->bmih.biWidth, bmp->bmih.biHeight, bmp->bmih.biBitCount);
    if (ret == -1)
    {
    printf("Error(CreateBitmap): can not CreateBitmap.\n");
    return -1;
    }
    //讀取圖像數據
    //由於4字節對齊格式
    fseek(fd, bmp->bmfh.bfOffBits, SEEK_SET); //定位到圖像數據區
    ret = fread(bmp->imageData, bmp->imageSize, 1, fd);
    if (ret == 0)
    {
    if (feof(fd)) //if the file pointer point to the end of the file
    {
    }
    if (ferror(fd)) //if error happened while read the pixel data
    {
    printf("Error(ReadBitmap): can not read the pixel data.\n");
    fclose(fd);
    return -1;
    }
    }
    //關閉文件
    fclose(fd);
    return 0;
    }

/**

  • 保存位圖到文件中去
  • 正確返回0,錯誤返回-1 *
  • 使用方法:
  • bmp=(Bitmap*)malloc(sizeof(Bitmap));
  • ret=SaveBitmap(path, bmp);
    

    /
    int SaveBitmap(char
    path, Bitmap* bmp, RGBQUAD *map = 0)
    {
    int ret = 0;
    FILE *fd;

    //檢查路徑是否正確
    int len = strlen(path) / sizeof(char);
    char ext[3];
    //check whether the path include the characters "bmp" at end
    strncpy(ext, &path[len - 3], 3);
    if (!(ext[0] == 'b' && ext[1] == 'm' && ext[2] == 'p'))
    {
    printf("Error(SaveBitmap): the extension of the file is not bmp.\n");
    return -1;
    }

    //打開文件
    fd = fopen(path, "wb");
    if (fd == 0)
    {
    printf("Error(SaveBitmap): can not open the image.\n");
    return -1;
    }

    //保存文件信息頭 14字節
    fwrite(&(bmp->bmfh.bfType), sizeof(WORD), 1, fd);
    fwrite(&(bmp->bmfh.bfSize), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmfh.bfReserved1), sizeof(WORD), 1, fd);
    fwrite(&(bmp->bmfh.bfReserved2), sizeof(WORD), 1, fd);
    fwrite(&(bmp->bmfh.bfOffBits), sizeof(DWORD), 1, fd);

    //保存位圖信息頭 40字節
    fwrite(&(bmp->bmih.biSize), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biWidth), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biHeight), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biPlanes), sizeof(WORD), 1, fd);
    fwrite(&(bmp->bmih.biBitCount), sizeof(WORD), 1, fd);
    fwrite(&(bmp->bmih.biCompression), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biSizeImage), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biXPelsPerMeter), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biYPelsPerMeter), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biClrUsed), sizeof(DWORD), 1, fd);
    fwrite(&(bmp->bmih.biClrImportant), sizeof(DWORD), 1, fd);

    //保存顏色表
    if (bmp->bmih.biBitCount == 8)
    {
    ret = fwrite(map, sizeof(RGBQUAD) , 256, fd);
    }
    if (ret == -1)
    {
    printf("Error(SaveBitmap): can not save Color Palette.\n");
    return -1;
    }

    //保存圖像數據
    ret = fwrite(bmp->imageData, bmp->imageSize, 1, fd);
    if (ret != 1)
    {
    printf("Error(SaveBitmap): can not save the pixel data.\n");
    return -1;
    }

    //關閉文件
    fclose(fd);
    return 0;
    }

int gray2ind(Bitmap* src, RGBQUAD map, Bitmap dst)
{

int r ,m;
CreateBitmap(dst, src->width, src->height, 8);


//灰度數據縮放
for (int i = 0; i<dst->height; i++)
{
    for (int j = 0; j<dst->width; j++)
    {
        r = *(src->imageData + src->widthStep*(src->height - 1 - i) + j);
        m = r / 16;

        *(dst->imageData + dst->widthStep*(dst->height - 1 - i) + j) = m;


    }
}
for (int i = 0; i<16; ++i)    //調色板轉換為0-1的小數
{
double gray = 0;

    gray = i*0.0667;
    (map + i)->rgbBlue = gray;
    (map + i)->rgbRed = gray;
    (map + i)->rgbGreen = gray;
    (map + i)->rgbReserved = 0;

}

return 0;

}

#endif // BMP_H_INCLUDED



最佳回答:


問題是,調色板 r g b三值相等啊,還有怎麼會變三通道呢

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved