服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言实现BMP格式图片转化为灰度

C语言实现BMP格式图片转化为灰度

2022-02-15 16:57爬行的菜鸟 C/C++

这篇文章主要为大家详细介绍了C语言实现BMP格式图片转化为灰度,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文为大家分享了C语言将BMP格式图片转化为灰度的具体代码,供大家参考,具体内容如下

代码如下:

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


#pragma pack(1)
typedef struct tagBITMAPFILEHEADER
{
  unsigned char bfType[2];//文件格式
  unsigned long bfSize;//文件大小
  unsigned short bfReserved1;//保留
  unsigned short bfReserved2;
  unsigned long bfOffBits; //DIB数据在文件中的偏移量
}fileHeader;
#pragma pack()
/*
位图数据信息结构
*/
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER
{
  unsigned long biSize;//该结构的大小
  long biWidth;//文件宽度
  long biHeight;//文件高度
  unsigned short biPlanes;//平面数
  unsigned short biBitCount;//颜色位数
  unsigned long biCompression;//压缩类型
  unsigned long biSizeImage;//DIB数据区大小
  long biXPixPerMeter;
  long biYPixPerMeter;
  unsigned long biClrUsed;//多少颜色索引表
  unsigned long biClrImporant;//多少重要颜色
}fileInfo;
#pragma pack()
/*
调色板结构
*/
#pragma pack(1)
typedef struct tagRGBQUAD
{
  unsigned char rgbBlue; //蓝色分量亮度
  unsigned char rgbGreen;//绿色分量亮度
  unsigned char rgbRed;//红色分量亮度
  unsigned char rgbReserved;
}rgbq;
#pragma pack()

int main()
{
  FILE *fp1 = fopen("C:\\Users\\Administrator\\Desktop\\data\\bmp\\image.bmp", "rb+");
  if (fp1 == NULL)
  {
      printf("打开文件fp1失败");
      exit(0);
  }

  FILE *fp2 = fopen("C:\\Users\\Administrator\\Desktop\\data\\bmp\\imageGray.bmp", "wb");
  if (fp1 == NULL)
  {
      printf("打开文件fp2失败");
      exit(0);
  }

  fileHeader * fh;
  fileInfo * fi;
  fh = (fileHeader *)malloc(sizeof(fileHeader));
  fi = (fileInfo *)malloc(sizeof(fileInfo));

  //读取位图头结构和信息头
  fread(fh, sizeof(fileHeader), 1, fp1);
  fread(fi, sizeof(fileInfo), 1, fp1);

  printf("\\\\\\\\\\\\\\\\\\\\原始图片信息\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
  printf("bmp文件头:\n");
  printf("bfSize:%d\n", fh->bfSize);
  printf("bfOffBits:%d\n", fh->bfOffBits);
  printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
  printf("bmp信息头\n");
  printf("结构体长度:%d \n", fi->biSize);
  printf("位图宽度:%d \n", fi->biWidth);
  printf("位图高度:%d \n", fi->biHeight);
  printf("位图平面数:%d \n", fi->biPlanes);
  printf("颜色位数:%d \n", fi->biBitCount);
  printf("压缩方式:%d \n", fi->biCompression);
  printf("实际位图数据占用的字节数:%d \n", fi->biSizeImage);
  printf("X方向分辨率:%d \n", fi->biXPixPerMeter);
  printf("Y方向分辨率:%d \n", fi->biYPixPerMeter);
  printf("使用的颜色数:%d \n", fi->biClrUsed);
  printf("重要颜色数:%d \n", fi->biClrImporant);
  printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");

  //修改信息头
  fi->biBitCount = 8;
  //fi->biSizeImage = ((fi->biWidth * 3 + 3) / 4) * 4 * fi->biHeight;
  fi->biSizeImage = fi->biHeight*fi->biWidth;
  //修改文件头
  fh->bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
  fh->bfSize = fh->bfOffBits + fi->biSizeImage;

  printf("\\\\\\\\\\\\\\\\\\\\修改后的图片信息\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
  printf("bmp文件头:\n");
  printf("bfSize:%d\n", fh->bfSize);
  printf("bfOffBits:%d\n", fh->bfOffBits);
  printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
  printf("bmp信息头\n");
  printf("结构体长度:%d \n", fi->biSize);
  printf("位图宽度:%d \n", fi->biWidth);
  printf("位图高度:%d \n", fi->biHeight);
  printf("位图平面数:%d \n", fi->biPlanes);
  printf("颜色位数:%d \n", fi->biBitCount);
  printf("压缩方式:%d \n", fi->biCompression);
  printf("实际位图数据占用的字节数:%d \n", fi->biSizeImage);
  printf("X方向分辨率:%d \n", fi->biXPixPerMeter);
  printf("Y方向分辨率:%d \n", fi->biYPixPerMeter);
  printf("使用的颜色数:%d \n", fi->biClrUsed);
  printf("重要颜色数:%d \n", fi->biClrImporant);
  printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");

  //创建调色板
  int i,j,k=0;
  rgbq *fq = (rgbq *)malloc(256 * sizeof(rgbq));
  for (i = 0; i<256; i++)
  {
      fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
  }
  //写入文件头、信息头、调色板
  fwrite(fh, sizeof(fileHeader), 1, fp2);
  fwrite(fi, sizeof(fileInfo), 1, fp2);
  fwrite(fq, sizeof(rgbq), 256, fp2);

  //将位图信息转为灰度
  //存储bmp一行的像素点
  //unsigned char ImgData[900][3];
  unsigned char ImgData[3000][3];
  //将灰度图像存到一维数组中
  //unsigned char grayData2[900];
  unsigned char ImgData2[3000];
  /*
  //错误的算法
  for (i = 0; i < fi->biHeight; i++)
  {
      for (j = 0; j < (fi->biWidth * 3 + 3) / 4 * 4; j++)
      {
          for (k = 0; k < 3; k++)
          {
              fread(&ImgData[j][k], 1, 1, fp1);
          }
      }
      for (j = 0; j < (fi->biWidth + 3) / 4 * 4; j++)
      {
          ImgData2[j] = int((float)ImgData[j][0] * 0.114 +
              (float)ImgData[j][1] * 0.587 +
              (float)ImgData[j][2] * 0.299);
      }
      //将灰度图信息写入
      fwrite(ImgData2, j, 1, fp2);
  }
  */
  /*
  //正确的算法(1)
  for (i = 0; i<fi->biHeight; i++)
  {
      for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
      {
          for (k = 0; k<3; k++)
          fread(&ImgData[j][k], 1, 1, fp1);
      }
      for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
      {
          ImgData2[j] = int((float)ImgData[j][0] * 0.114 +
              (float)ImgData[j][1] * 0.587 +
              (float)ImgData[j][2] * 0.299);
      }
      //将灰度图信息写入
      fwrite(ImgData2, j, 1, fp2);
  }
  */
  //正确算法(2)
  unsigned char * * bmp_data;
  bmp_data = new unsigned char*[fi->biHeight]; //声明一个指针数组
  unsigned char *data288 = new unsigned char[fi->biHeight*fi->biWidth];

  for (i = 0; i<fi->biHeight; i++)
      bmp_data[i] = new unsigned char[(fi->biWidth * 3 + 3) / 4 * 4]; //每个数组元素也是一个指针数组
  for (i = 0; i<fi->biHeight; i++)
      for (j = 0; j<(fi->biWidth * 3 + 3) / 4 * 4; j++)
          fread(&bmp_data[i][j], 1, 1, fp1);//每次只读取一个字节,存入数组

  for (i = 0; i<fi->biHeight; i++)//将24位真彩色转换成灰度图
      for (j = 0; j<fi->biWidth; j++){
      data288[fi->biWidth*i + j] = ((unsigned char)((float)bmp_data[i][3 * j] * 0.114 + (float)bmp_data[i][3 * j + 1] * 0.587 + (float)bmp_data[i][3 * j + 2] * 0.299));
      }

  fwrite(data288, fi->biSizeImage, 1, fp2);
  free(fh);
  free(fi);
  free(fq);
  fclose(fp1);
  fclose(fp2);
  printf("success\n");
  return 0;
}

C语言实现BMP格式图片转化为灰度

C语言实现BMP格式图片转化为灰度

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/zb774095236/article/details/89378571

延伸 · 阅读

精彩推荐
  • C/C++学习C++编程的必备软件

    学习C++编程的必备软件

    本文给大家分享的是作者在学习使用C++进行编程的时候所用到的一些常用的软件,这里推荐给大家...

    谢恩铭10102021-05-08
  • C/C++C/C++经典实例之模拟计算器示例代码

    C/C++经典实例之模拟计算器示例代码

    最近在看到的一个需求,本以为比较简单,但花了不少时间,所以下面这篇文章主要给大家介绍了关于C/C++经典实例之模拟计算器的相关资料,文中通过示...

    jia150610152021-06-07
  • C/C++C++之重载 重定义与重写用法详解

    C++之重载 重定义与重写用法详解

    这篇文章主要介绍了C++之重载 重定义与重写用法详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    青山的青6062022-01-04
  • C/C++深入理解goto语句的替代实现方式分析

    深入理解goto语句的替代实现方式分析

    本篇文章是对goto语句的替代实现方式进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网7342020-12-03
  • C/C++详解c语言中的 strcpy和strncpy字符串函数使用

    详解c语言中的 strcpy和strncpy字符串函数使用

    strcpy 和strcnpy函数是字符串复制函数。接下来通过本文给大家介绍c语言中的strcpy和strncpy字符串函数使用,感兴趣的朋友跟随小编要求看看吧...

    spring-go5642021-07-02
  • C/C++C语言中炫酷的文件操作实例详解

    C语言中炫酷的文件操作实例详解

    内存中的数据都是暂时的,当程序结束时,它们都将丢失,为了永久性的保存大量的数据,C语言提供了对文件的操作,这篇文章主要给大家介绍了关于C语言中文件...

    针眼_6702022-01-24
  • C/C++C语言实现电脑关机程序

    C语言实现电脑关机程序

    这篇文章主要为大家详细介绍了C语言实现电脑关机程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    xiaocaidayong8482021-08-20
  • C/C++c++ 单线程实现同时监听多个端口

    c++ 单线程实现同时监听多个端口

    这篇文章主要介绍了c++ 单线程实现同时监听多个端口的方法,帮助大家更好的理解和学习使用c++,感兴趣的朋友可以了解下...

    源之缘11542021-10-27