家人萌 我因为这个作业爆炸了好多天...所以我想发一下

菜鸡一个 别骂别骂 欢迎指正

 关于这个作业要先了解一下这些登西...

1)BMP 位图的结构

1、BMP文件头(14字节) ,文件的第0字节到第13字节为BMP图像的文件头。BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。

typedef struct tagBITMAPFILEHEADER

{

WORD bfType; // 位图文件的类型,必须为BM(0-1字节)

DWORD bfSize; // 整个位图文件的大小,以字节为单位(2-5字节)

WORD bfReserved1; // 位图文件保留字,必须为0(6-7字节)

WORD bfReserved2; // 位图文件保留字,必须为0(8-9字节)

DWORD bfOffBits; // 位图数据的起始位置,以相对于位图(10-13字节)

}

2、位图信息头(40字节),文件的第14个字节到第53个字节为BMP图像的信息头,位图信息头数据用于说明位图的尺寸等信息。在这部分读取位图的长和宽

typedef struct tagBITMAPINFOHEADER {

DWORD biSize; // 本结构所占用字节数(14-17字节)

LONG biWidth; // 位图的宽度,以像素为单位(18-21字节)

LONG biHeight; // 位图的高度,以像素为单位(22-25字节)

WORD biPlanes; // 目标设备的级别,必须为1(26-27字节)

WORD biBitCount;// 每个像素所需的位数,必须是1(双色), 4(16色),8(256色)或24(真彩色)之一(28-29字节)

DWORD biCompression; // 位图压缩类型,必须是 0(不压缩), 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一(30-33字节)

DWORD biSizeImage; // 位图数据部分的大小,以字节为单位(34-37字节)

LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数(38-41字节)

LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数(42-45字节)

DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数(46-49字节)

DWORD biClrImportant;// 位图显示过程中重要的颜色数(50-53字节)

}

3.调色板

调色板用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:

typedef struct tagRGBQUAD {

BYTE rgbBlue;    // 蓝色的亮度(值范围为0-255)

BYTE rgbGreen;   // 绿色的亮度(值范围为0-255)

BYTE rgbRed;     // 红色的亮度(值范围为0-255)

BYTE rgbReserved;// 保留,必须为0

}

调色板中RGBQUAD结构数据的个由biBitCount来确定:

当biBitCount=1,4,8时,分别有2,16,256个表项;  2的n次方吼

当biBitCount=24时,该BMP图像就是24Bit真彩图,没有调色板项

还有!!!每个表项为4个字节

4、位图数据

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。

位图的一个像素值所占的字节数由biBitCount来确定:

当biBitCount=1时,8个像素占1个字节;

当biBitCount=4时,2个像素占1个字节;

当biBitCount=8时,1个像素占1个字节;

当biBitCount=24时,1个像素占3个字节;(每个像素的颜色信息每3个字节一组,按BGR的顺序存放,其中每个字节只存一个颜色值。颜色值范围是0~255,用无符号char型存储)

!!!Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充

24位真彩图每一行占的实际字节数 =((宽度*3+3)/4)*4

灰度图每一行占的实际字节数= ((宽度+3)/4)*4

2)读取文件

利用fstream读文件

要注意BMP文件每个部分所占的字节数,因为不是每个部分的信息要需要读取,所以要利用seekg函数移动读文件的指针位置,还有就是利用read函数读取文件时,也要确定读取的字节数。

BMP的文件头没有要读取的内容,所以移动指针“跳过”文件头,然后读取信息头,可以利用sizeof()得到文件头和信息头所占的字节数。调色板部分也不需要读取,如果是24位位图,没有调色板,可以直接向下进行,其他位图都需要得到调色板的大小然后“跳过”,读取下一部分的位图数据。

这个作业写的 只能读8位和24位的 而且只是读入数据 没有修改

Image.h

#ifndef IMAGE_H
#define IMAGE_H
#include<iostream>
#include<fstream>
#include<windows.h>
#include<cmath>
#include<string>
using namespace std;
class Image {friend Image& operator+(Image& img1, Image& img2);
public:Image();Image(string fliename);~Image();long getWidth();long getHeight();float Average();float Variance();void show();
private:long m_width;long m_height;int m_bitCount;unsigned char* m_pData;
};Image& operator+(Image& img1, Image& img2);#endif

Image.cpp

#include"Image.h"Image::Image() {this->m_width = 0;this->m_height = 0;this->m_pData = NULL;
}
Image::Image(string filename) {//bmp文件的地址ifstream open(filename, ios::binary);if (!open.is_open()) {cout <<filename<< "文件打开成功" << endl;}//跳过位图文件头open.seekg(sizeof(BITMAPFILEHEADER));//读取位图信息头BITMAPINFOHEADER a;open.read((char*)&a, sizeof(BITMAPINFOHEADER));m_height = a.biHeight;m_width = a.biWidth;m_bitCount= a.biBitCount;cout << "文件"<<filename << "为" << m_bitCount << "位位图" << endl;cout << "高度:" << m_height << endl;cout << "宽度:" << m_width << endl;//如果是24位位图 无调色板 直接向下进行//其他位图有调色板 需要跳过调色板读取位图数据if (m_bitCount != 24) {open.seekg(4 * (pow(2.0, m_bitCount)));//调色板大小 4*色彩数}//读取位图数据(有0补位)if(m_bitCount==8){m_pData = new unsigned char[m_height * (((m_width + 3) / 4) * 4)];open.read((char*)m_pData, m_height * (((m_width + 3) / 4) * 4));}else if (m_bitCount == 24){m_pData = new unsigned char[m_height * ((m_width * 3 + 3) / 4) * 4];open.read((char*)m_pData, m_height * ((m_width * 3 + 3) / 4) * 4);}open.close();
}
Image::~Image() {delete[] m_pData;
}
long Image::getHeight(){return m_height;
}
long Image::getWidth() {return m_width;
}float Image::Average() {try {if (m_pData == NULL)throw exception("位图数据为空!");if (m_bitCount != 8 && m_bitCount != 24)throw m_bitCount;float sum = 0;if(m_bitCount==8){for (int i = 0; i < m_height * ((m_width + 3) / 4) * 4; i++) {sum += m_pData[i];}return sum * 1.0 / (m_height * m_width);}else if (m_bitCount == 24) {for (int i = 0; i < m_height * ((m_width*3 + 3) / 4) * 4; i++) {sum += m_pData[i];}return sum * 1.0 / (m_height * m_width*3);}}catch (exception error) {cout << error.what() << endl;return 0;}catch (int) {cout << "无法对" << m_bitCount << "位位图计算 T_T" << endl;return 0;}
}float Image::Variance() {try {if (m_pData == NULL)throw exception("位图数据为空!");if (m_bitCount != 8 && m_bitCount != 24)throw m_bitCount;float sum = 0;long long count = 0;//每行补位0的个数int n = (m_width % 4 == 0) ? 0 : 4 - m_width % 4;if(m_bitCount==8){for (int i = 0; i < m_height; i++) {for (int j = 0; j < m_width; j++) {sum += ((m_pData[count] - this->Average()) * (m_pData[count] - this->Average()));count++;}if (n != 0)count += (n - 1);}}else if (m_bitCount == 24) {for (int i = 0; i < m_height; i++) {for (int j = 0; j < m_width; j++) {float sum1 = 0, avg1 = 0;for (int k = 0; k < 3; k++) {sum1 += m_pData[count];count += 1;}avg1 = sum1 * 1.0 / 3;sum += ((Average() - avg1) * (Average() - avg1));}if (n != 0)count += (n - 1);}}return sum * 1.0 / (m_height * m_width);}catch (exception error) {cout << error.what() << endl;return 0;}catch (int) {cout << "无法对" << m_bitCount << "位位图计算 T_T" << endl;return 0;}
}Image& operator+(Image& img1, Image& img2) {try {if (img1.getHeight() != img2.getHeight() || img1.getWidth() != img2.getWidth())throw exception("两个位图长宽不同 无法运算");for (int i = 0; i < img1.getHeight() * ((img1.getWidth() + 3) / 4) * 4; i++) {if (img1.m_pData[i] + img2.m_pData[i] <= 255) {img1.m_pData[i] += img2.m_pData[i];}else {img1.m_pData[i] = (img1.m_pData[i] + img2.m_pData[i]) % 255;}}return img1;}catch (exception error) {cout << error.what() << endl;}
}void Image::show() {cout <<"位图平均值:" << Average() << endl;cout << "位图方差:" << Variance() << endl;
}

Test.cpp

#include"Image.h"
int main() {string filename1, filename2, filename3, filename4, filename5;//F:\\Image\\test01.bmp F:\\Image\\test02.bmp F:\\Image\\test03.bmp F:\\Image\\test04.bmp F:\\Image\\test05.bmpcout << "输入5个位图的地址" << endl;cin >> filename1 >> filename2 >> filename3 >> filename4 >> filename5;//样例信息:Image img1(filename1);//8位Image img2(filename2);//8位Image img3(filename3);//8位 (不同大小Image img4(filename4);//24位Image img5(filename5);//24位Image img6;//空cout << "img1:" << endl;img1.show();cout << "img2:" << endl;img2.show();cout << "img1+img2:" << endl;(img1 + img2).show();cout << "img1+img3:" << endl;img1 + img3;cout << "img4:" << endl;img4.show();cout << "img5:" << endl;img5.show();cout << "img6:" << endl;img6.show();}

c++读取8位和24位BMP位图数据 俺的作业相关推荐

  1. node 16位 转24位_同时将24位和32位BMP图像顺时针旋转90度

    上一次我们将24位的皮卡丘旋转了90度,但是后来改需求了...要求把32位的.bmp文件也能够旋转90度.上次就懵逼的我继续懵逼,只好继续转向CSDN求助. 浏览了各种求助帖(还找到了数年前的信科大一 ...

  2. C#图片灰度处理(位深度24→位深度8),用灰度数组byte[]新建一个8位灰度图像Bitmap 。...

    原文:C#图片灰度处理(位深度24→位深度8) #region 灰度处理/// <summary>/// 将源图像灰度化,并转化为8位灰度图像./// </summary>// ...

  3. 8位, 16位,24位,32位图片显示原理及对比

    我们都知道一张图片可以保存为很多种不同的格式,比如bmp/png/jpeg/gif等等.这个是从文件格式的角度看,我们抛开文件格式,看图片本身,我们可以分为8位, 16位, 24位, 32位等. 单击 ...

  4. 2021-08-04 jpg和png批量转化8位到24位,相互转化!

    1.批量转化从8位到24位深度,jpg和png都能一起批量转化 import os import numpy as np import PIL from PIL import Image import ...

  5. matlab修改图片位深度_BMP位图32位转为24位深度

    帮朋友做一个视频采集和基本处理功能,要求的是.bmp格式 几天下来,通过directshow进行视频采集,并抓去图片保存,按照要求进行业务处理,以前的处理程序是基于RGB24 而显示器是32位真彩色, ...

  6. node 16位 转24位_C代码实现16位和32位数据字节序转换

    点击上方公众号名称关注,获得更多内容 ✎ 编 者 悟 语 每天给自己一个存在的意识,这样才会有一颗认真的心. 文 章 导 读 今天给大家用C代码实现下大小端字节序的转换代码,感谢的小伙伴可以拿下来撸一 ...

  7. (tip_修订0618)bmp 32位转24位

    没什么效率可言,完全是解决问题,             Bitmap bmp = new Bitmap(320, 240, PixelFormat.Format24bppRgb);          ...

  8. 【Qt】QImage加载bmp位图数据

    QImage直接加载bmp文件 QImage image(image.bmp); QImage加载已经获取的bmp数据 unsigned char *imageData = NULL; int ima ...

  9. c语言读取24位BMP文件并实现翻转90度、180度、270度

    BMP图片格式 BMP图片,是Bitmap(位图)的简称,它是windows显示图片的基本格式.在windows下,任何格式的图片文件(包括视频播放)都要转化为位图才能显示出来.各种格式的图片文件也都 ...

最新文章

  1. python二维元组_python中读入二维csv格式的表格方法详解(以元组/列表形式表示)
  2. pve rust 能拆家吗_RUST:2020年9月第四周:向上向上再向上!
  3. linux 单个网卡配置多个IP
  4. 训练 yolo 模型
  5. server之后安装ssms失败 安装sql_关于SQL安装失败的解决方法
  6. Android AsyncTask两种线程池分析和总结
  7. add-apt-repository:找不到命令_嵌入式开发之交叉编译程序万能命令_以freetype为例...
  8. scp windows 和 linux 远程复制 (双向)
  9. mysql lock trx id_MySQL中RR模式下死锁一例
  10. C++常见面试题-30道
  11. network 关于PV,网站访问量和服务器带宽的选择
  12. python上机实践_python程序设计江红上机实践答案
  13. android音频杂音问题_如何让短视频音质更好,AE+PR短视频音频输出处理讲解
  14. java 远程登录linux_使用java登录远程LINUX并对服务实现各种操作
  15. iOS动画和第三方插件学习网址
  16. JSON.stringify用法
  17. 人民币大写金额转换为数字
  18. 学习笔记 css border-radius
  19. li标签中hover的使用及li标签的样式
  20. 计算机二级python看什么书好_2021年全国计算机二级Python备考指导

热门文章

  1. uniapp自定义组件在h5显示,微信小程序不显示?
  2. 混合app框架之uni-app---grid布局
  3. 4-11 你的比萨和我的比萨
  4. 基于java自动售货机 课程设计_JAVA-案例-自动售货机.pdf
  5. html绝对定位怎么页面居中,css绝对定位如何居中?css绝对定位居中的四种实现方法...
  6. es6入门到五连绝世之四杀(quadra kill )
  7. 聊聊什么是 i18n?JavaScript 中的 i18n 基本概念
  8. ProSpec CCL1/ I-309研究方案
  9. 100 多个免费 API 接口分享,调用完全不限次数,以后总用得着
  10. Java面试系列-MongoDB