24位真彩色位图和8位灰度位图相互转换(C语言实现)

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

FILE *fpSrcBmpfile;
FILE *fpDestBmpfile;

void GetBmpHeader(PBITMAPFILEHEADER, PBITMAPINFOHEADER);
void ChangeBmpHeader(PBITMAPFILEHEADER, PBITMAPINFOHEADER, WORD);
void SetBmpHeader(const PBITMAPFILEHEADER, const PBITMAPINFOHEADER);
void SetRGBQUAD();
void RgbToGrade(); // 24位真彩色转8位灰度
void GradeToRgb(); // 8位灰度位图转24位真彩色

int main(int argc, char *argv[])
{
    BITMAPFILEHEADER bfheader; // bmp文件头
    BITMAPINFOHEADER biheader; // 位图信息头
    memset(&bfheader, 0, sizeof(BITMAPFILEHEADER));
    memset(&biheader, 0, sizeof(BITMAPINFOHEADER));
    if(argc != 2)
    {
        puts("/n/t***Error  : I need two parameters.");
        puts("/t   Example: RgbToQuad.exe D://flower.bmp");
        system("pause>nul");
        exit(EXIT_SUCCESS);
    }
    if((fpSrcBmpfile = fopen(argv[1], "rb")) == NULL) {
        perror("/t***Open file failed:(read)");
        system("pause>nul");
        exit(EXIT_FAILURE);
    }
    GetBmpHeader(&bfheader, &biheader);
    if(bfheader.bfType != 0x4D42) {
        puts("/t  *End: This file is not bitmap file.");
        system("pause>nul");
        exit(EXIT_SUCCESS);
    }

    if(biheader.biBitCount != 24 && biheader.biBitCount != 8) {
        puts("/n  *End: This bmp file is neither a 24bit nor a 8bit bitmap.");
        system("pause>nul");
        exit(EXIT_SUCCESS);
    }
    // 对于采用了游程长度编码方法进行压缩的8位位图 不能按照本算法转为24位位图
    if(biheader.biBitCount == 8 && biheader.biCompression != BI_RGB) {
        puts("/n   *End: This 8bit bmp file is not BI_RGB type");
        system("pause>nul");
        exit(EXIT_SUCCESS);
    }
    if((fpDestBmpfile = fopen("D://_Done_.bmp", "wb")) == NULL) {
        perror("fopen failed :(write)");
        system("pause>nul");
        exit(EXIT_FAILURE);
    }
    switch(biheader.biBitCount) {
        case 8 : GradeToRgb(); break;
        case 24: RgbToGrade(); break;
        default: break;
    }
    fclose(fpDestBmpfile);
    fclose(fpSrcBmpfile);
    system("pause>nul");
    return 0;
}
void GetBmpHeader(PBITMAPFILEHEADER pbfheader, PBITMAPINFOHEADER pbiheader)
{
    fread(pbfheader, sizeof(BITMAPFILEHEADER), 1,fpSrcBmpfile);
    fread(pbiheader, sizeof(BITMAPINFOHEADER), 1,fpSrcBmpfile);
}

void ChangeBmpHeader(PBITMAPFILEHEADER pbfheader, PBITMAPINFOHEADER pbiheader, WORD wType)
{
    pbiheader->biBitCount  = wType; // 24 或者 8
    pbiheader->biClrUsed   = (wType == 24) ? 0 : 256;
    pbfheader->bfOffBits   = 54 + pbiheader->biClrUsed * sizeof(RGBQUAD);
    pbiheader->biSizeImage = ((((pbiheader->biWidth * pbiheader->biBitCount) + 31) & ~31) / 8) * pbiheader->biHeight;
    pbfheader->bfSize      = pbfheader->bfOffBits + pbiheader->biSizeImage;
}

void SetBmpHeader(const PBITMAPFILEHEADER pbfheader, const PBITMAPINFOHEADER pbiheader)
{
    fwrite(pbfheader, sizeof(BITMAPFILEHEADER), 1, fpDestBmpfile);
    fwrite(pbiheader, sizeof(BITMAPINFOHEADER), 1, fpDestBmpfile);
}

void SetRGBQUAD()
{
    int i;
    RGBQUAD rgbquad[256];
    for(i=0;i<256;i++) {
        rgbquad[i].rgbBlue     = i;
        rgbquad[i].rgbGreen    = i;
        rgbquad[i].rgbRed      = i;
        rgbquad[i].rgbReserved = 0;
    }
    fwrite(rgbquad, 256 * sizeof(RGBQUAD), 1, fpDestBmpfile);
}

void RgbToGrade() {
    LONG w, h;
    COLORREF rgb;
    BYTE r, g, b;
    BYTE gray;
    BYTE count24, count8;
    BYTE Bmpnul = 0;
    BITMAPFILEHEADER bfheader; // bmp文件头
    BITMAPINFOHEADER biheader; // 位图信息头
    memset(&bfheader, 0, sizeof(BITMAPFILEHEADER));
    memset(&biheader, 0, sizeof(BITMAPINFOHEADER));
    rewind(fpSrcBmpfile);
    GetBmpHeader(&bfheader, &biheader);
    ChangeBmpHeader(&bfheader, &biheader, 8);
    SetBmpHeader(&bfheader, &biheader);
    SetRGBQUAD();
    count24 =  ( 4 - ( biheader.biWidth * 3 ) % 4 ) % 4;
    count8  =  ( 4 - ( biheader.biWidth     ) % 4 ) % 4;
    for(h=biheader.biHeight-1; h>=0; h--) {
        for(w=0; w<biheader.biWidth; w++) {
            fread(&rgb, 3, 1, fpSrcBmpfile);
            if(feof(fpSrcBmpfile)) {
                break;
            }
            // rgb: 0x00bbggrr
            r = GetBValue(rgb);
            g = GetGValue(rgb);
            b = GetRValue(rgb);
            // 参见: http://zhidao.baidu.com/question/152910968.html
            gray = (BYTE)( ( 77 * r + 151 * g + 28 * b) >> 8 ); // 24位转8位核心算法
            fwrite(&gray, sizeof(gray), 1, fpDestBmpfile);
        } // for(w
        fseek(fpSrcBmpfile, count24, SEEK_CUR);
        fwrite(&Bmpnul, 1, count8, fpDestBmpfile);
    } // for(h=...
}
void GradeToRgb()
{
    LONG w, h;
    COLORREF rgb;
    BYTE r, g, b;
    BYTE gray;
    BYTE count24, count8; // 24位位图、8位位图每个扫描行需要填充的0的个数
    BYTE Bmpnul = 0;
    BITMAPFILEHEADER bfheader; // bmp文件头
    BITMAPINFOHEADER biheader; // 位图信息头
    memset(&bfheader, 0, sizeof(BITMAPFILEHEADER));
    memset(&biheader, 0, sizeof(BITMAPINFOHEADER));
    rewind(fpSrcBmpfile);
    GetBmpHeader(&bfheader, &biheader);
    ChangeBmpHeader(&bfheader, &biheader, 24);
    SetBmpHeader(&bfheader, &biheader);
    fseek(fpSrcBmpfile, 256 * sizeof(RGBQUAD), SEEK_CUR); // 跳过颜色表部分 因为24位位图不需要颜色表
    count24 =  ( 4 - ( biheader.biWidth * 3 ) % 4 ) % 4;
    count8  =  ( 4 - ( biheader.biWidth     ) % 4 ) % 4;
    for(h=biheader.biHeight-1; h>=0; h--) {
        for(w=0; w<biheader.biWidth; w++) {
            fread(&gray, 1, 1, fpSrcBmpfile);
            if(feof(fpSrcBmpfile)) {
                break;
            }
            r = g = b = gray; // 8位转24位核心算法
            rgb = RGB(b, g, r);
            fwrite(&rgb, 3, 1, fpDestBmpfile);
        } // for(w
        fseek(fpSrcBmpfile, count8, SEEK_CUR);
        fwrite(&Bmpnul, 1, count24, fpDestBmpfile);
    } // for(h
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值