C++读取bmp格式图片

article/2025/8/28 8:10:31

类的格式按照bmp的文件头、信息头、调色板和数据域写好即可
因为图片是按字节读的,所以要强制让编译器不对结构体进行字节对齐,否则会出错
因为bmp格式规定存储时每行的像素数要补齐至4的整数倍,所以读入和写出时要加一些对应的操作
——————————————————————————————————————————————
2019.9.6更新
增加了边缘检测、均值滤波和中值滤波
详情见注释

#include <bits/stdc++.h>#pragma GCC optimize(3)
using namespace std;typedef unsigned short w;
typedef unsigned int dw;class bmp
{
#pragma pack(1)//取消编译器的字节对齐struct FileHead{w type;dw size;w reserved1, reserved2;dw offset;} fileHead{};#pragma pack(1)struct InfoHead{dw size, width, height;w planes; //图像的位面数w bitNum; //每个像素的位数dw compression; //压缩类型dw imgSize; //单位为字节dw xPelsPerMeter, yPelsPerMeter;dw colorNum; //使用的色彩数dw colorImportantNum; //重要的颜色数} infoHead{};#pragma pack(1)struct Palette{w b, g, r, reversed;} palette{};struct Sum;
#pragma pack(1)struct Pixel{unsigned char b, g, r;//24位位图按照BGR的顺序存放, 32位BGRA
//        friend ostream &operator<<(ostream &out, const Pixel a)
//        {
//            return out << '[' << (unsigned) a.b << ' ' << (unsigned) a.g << ' ' << (unsigned) a.r << ']';
//        }Pixel(unsigned char b = 0, unsigned char g = 0, unsigned char r = 0) : b(b), g(g), r(r){}Pixel &operator=(const Sum &a){b = (unsigned char) a.b;g = (unsigned char) a.g;r = (unsigned char) a.r;}bool operator<(const Pixel &a) const{if (b == a.b){if (g == a.g)return r < a.r;return g < a.g;}return b < a.b;}};struct Sum  //用来维护二维前缀和的结构体{           // 因为pixel的rgb都是1字节,求和会溢出,所以另开一个int b, g, r;Sum(int b = 0, int g = 0, int r = 0) : b(b), g(g), r(r){}template<typename T>//既可以+=Sum, 也可以+=PixelSum &operator+=(const T &a){b += a.b;g += a.g;r += a.r;return *this;}Sum operator+(const Sum &a){return {b + a.b, g + a.g, r + a.r};}Sum operator-(const Sum &a){return {b - a.b, g - a.g, r - a.r};}template<typename T>Sum &operator-=(const T &a){b -= a.b;g -= a.g;r -= a.r;return *this;}Sum &operator/=(const int k){b /= k;g /= k;r /= k;}};inline int pos(int i, int j){return i * realWidth + j;}ifstream in;ofstream out;int realWidth{};
public:bmp() = default;~bmp(){delete[] img;}unsigned int n{};Pixel *img = nullptr;bool open(const string &file){in.open(file, ios::in | ios::binary);if (!in)return 0 & puts("无法打开文件");return true;}void read(){if (!in){puts("未打开文件");return;}in.read((char *) &fileHead, sizeof(fileHead));in.read((char *) &infoHead, sizeof(infoHead));realWidth = ((infoHead.width - 1) / 4) * 4 + 4;n = infoHead.height * realWidth;img = new Pixel[infoHead.height * realWidth];in.read((char *) img, sizeof(Pixel) * n);in.close();}Pixel &operator[](int id){return img[id];}const InfoHead &getInfoHead() const{return infoHead;}const FileHead &getFileHead() const{return fileHead;}void write(const string &file){out.open(file, ios::out | ios::binary);out.write((char *) &fileHead, sizeof(fileHead));out.write((char *) &infoHead, sizeof(infoHead));out.write((char *) img, sizeof(Pixel) * n);out.close();}void toGrayImg(){unsigned char val;for (int i = 0; i < n; ++i){val = 0.587 * img[i].g + 0.299 * img[i].r + 0.114 * img[i].b;img[i] = Pixel(val, val, val);//rgb都设为一样就是灰度图了}}void meanFiltering(int k)//k是半径, 如k取2, 求均值的范围为3 * 3{--k;//均值滤波, 对每个大小为(2 * k + 1) * (2 * k + 1)的子矩阵求和再平均,把中心的值改为均值。Sum *dp = new Sum[realWidth * infoHead.height];//这里用了二维前缀和来加速
#define summ(x1, y1, x2, y2) (dp[pos(x2, y2)]+(x1 && y1 ? dp[pos(x1-1, y1-1)] : 0)-(x1 ? dp[pos(x1-1, y2)] : 0)-(y1 ? dp[pos(x2, y1-1)] : 0))for (int i = 0; i < infoHead.height; ++i)//预处理二维前缀和{for (int j = 0; j < infoHead.width; ++j){dp[pos(i, j)] += img[pos(i, j)];if (i)dp[pos(i, j)] += dp[pos(i - 1, j)];if (j)dp[pos(i, j)] += dp[pos(i, j - 1)];if (i && j)dp[pos(i, j)] -= dp[pos(i - 1, j - 1)];}}Sum val;for (int i = 0; i < infoHead.height; ++i){for (int j = 0; j < infoHead.width; ++j){if (i < k || j < k || i + k > infoHead.height - 1 || j + k > infoHead.width - 1) continue;val = summ(i - k, j - k, i + k, j + k);val /= (k * 2 + 1) * (k * 2 + 1);img[pos(i, j)] = Pixel((unsigned char) val.b, (unsigned char) val.g, (unsigned char) val.r);}}delete[] dp;}Pixel getMedian(int x, int y, int k){vector<Pixel> a;a.clear();for (int i = x - k; i <= x + k; ++i)for (int j = y - k; j <= y + k; ++j)a.push_back(img[pos(i, j)]);
//        nth_element(a.begin(), a.begin() + ((2 * k + 1) * (2 * k + 1)) / 2, a.end());sort(a.begin(), a.end());return a[((2 * k + 1) * (2 * k + 1)) / 2];}void solve()//增加噪声,用于检验中值滤波和均值滤波{for (int i = 0; i < infoHead.height; ++i){for (int j = 0; j < infoHead.width; ++j){if (rand() < 1000)img[pos(i, j)] = Pixel(255, 255, 255);}}}void medianFiltering(int k)//k是半径{//中值滤波,用子矩阵的中位数替换中心的值Pixel *IMG = new Pixel[infoHead.height * ((infoHead.width - 1) / 4 * 4 + 4)];--k;for (int i = k; i + k < infoHead.height; ++i){for (int j = k; j + k < infoHead.width; ++j){IMG[pos(i, j)] = getMedian(i, j, k);}}for (int i = k; i + k < infoHead.height; ++i){for (int j = k; j + k < infoHead.width; ++j){img[pos(i, j)] = IMG[pos(i, j)];}}delete[]IMG;}void toEdge()//边缘检测{//采用梯度下降法,对x方向和y方向分别求差分,每个像素处保存一个向量(x, y), 向量的模小于阈值的像素涂黑,其余涂白int *difR = new int[realWidth * infoHead.height], *difC = new int[realWidth * infoHead.height];for (int i = 1; i < infoHead.height; ++i){for (int j = 0; j < infoHead.width; ++j){difR[pos(i, j)] = img[pos(i, j)].b - img[pos(i - 1, j)].b;}}for (int i = 0; i < infoHead.height; ++i){for (int j = 1; j < infoHead.width; ++j){difC[pos(i, j)] = img[pos(i, j)].b - img[pos(i, j - 1)].b;}}for (int i = 0; i < n; ++i){if (sqrt(difR[i] * difR[i] + difC[i] * difC[i]) < 6)img[i] = Pixel(255, 255, 255);elseimg[i] = Pixel(0, 0, 0);}delete[] difC;delete[] difR;}
};int main()
{bmp pic;pic.open("test.bmp");pic.read();
//    printf("%u %u\n", pic.getInfoHead().imgSize, pic.getInfoHead().width);
//    pic.toGrayImg();
//    pic.solve();
//    pic.write("g01.bmp");pic.toEdge();//    pic.meanFiltering(2);pic.medianFiltering(2);pic.write("test.bmp");return 0;
}

原图
在这里插入图片描述
直接边缘检测的效果
在这里插入图片描述
中值滤波后的效果
在这里插入图片描述


http://chatgpt.dhexx.cn/article/Cl0fhjvS.shtml

相关文章

android 图片格式,常见图片格式详解

做了几年有关图形、图像的工作,对图片格式算是小有经验,在此写成一文章总结下。虽然一开始并不想讲很理论的东西,但写完后发现几乎全是理论,细想一下关于图片格式的知识本身就是理论的东西,囧~~ 那就力求用最简单的方式将这些“理论”讲清楚吧。 常见的图片格式有bmp, jpg…

Qt之生成png/jpg/bmp格式图片

Qt之生成png/jpg/bmp格式图片 一、问题描述二、显示效果三、核心代码示例 一、问题描述 有时候需要把Qt绘制的一些图形保存为png/jpg/bmp格式的图片&#xff0c;下面就根据自己写的一个简单的测试程序来讲解一下Qt中保存图片的方法。本文主要讲解使用Qpainter和QImage组合使用…

MFC详解显示BMP格式图片

本文主要是讲述《数字图像处理》系列栏目中的第一篇文章.主要详细介绍了BMP图片格式,同时使用C和MFC显示BMP格式,主要结合自己的《数字图像处理》课程和以前的项目叙述讲解. 一.BMP图片格式定义 BMP文件格式是Windows操作系统推荐和支持的标准图像文件格式,是一种将内存或显示…

bmp格式说明

bmp24位位图格式 创建bmp24位位图格式的图片 打开Windows系统自带的画图软件&#xff0c;如下&#xff1a; 点击“文件 > 另存为”&#xff0c;在弹出的界面中有4种bmp格式可以选择&#xff0c;如下&#xff1a; 不知道bmp格式是不是只有上面的4种&#xff0c;还是有更多…

如何批量将 bmp 格式图片转换为 png 格式

概要&#xff1a;bmp 格式是纹的操作系统当中非常常见的一种图片格式&#xff0c;这种格式的特点是包含的图像信息较丰富&#xff0c;几乎不进行压缩&#xff0c;所以导致了它存在一个很大的缺点&#xff0c;那就是占用磁盘空间过大&#xff0c;那么我们怎么将 bmp 格式的图片转…

将BMP 格式图片转换为 JPEG 格式【c语言】

源码链接: https://blog.csdn.net/qq_44394952/article/details/122587475?spm1001.2014.3001.5502. 一、任务及目标 利用c语言&#xff0c;通过将 RGB 信息转换为 YCrCb 信息、离散余弦变化、量化和 z 型编码&#xff0c;再进行游程编码和霍夫曼编码&#xff0c;最后进行尾…

如何批量将 bmp 格式图片转换转换为 jpg

概要&#xff1a;png 和 jpg 这两种格式的图片相信大家都非常熟悉&#xff0c;但是 bmp 格式的图片可能大家接触得并没有那么多&#xff0c;bmp 是 Windows 操作系统中的标准图像文件格式&#xff0c;能够被多种 Windows 应用程序所支持&#xff0c;因此格式的图片在 Windows 操…

bmp格式图的解析

文章目录 前言 一、bmp格式图的特点 二、bmp格式图的解析 总结 前言 在图像处理中经常会遇到BMP格式图的解析问题&#xff0c;本文简单介绍了bmp格式图的解析方式&#xff0c;并附上相应的C代码。 一、bmp格式图的特点 bmp图通常由图片的头文件信息和像素数据组成&#xff0c…

R语言与多元线性回归分析计算实例

6.3.7 计算实例 例 6.9 某大型牙膏制造企业为了更好地拓展产品市场&#xff0c;有效地管理库存&#xff0c;公司董事会要求销售部门根据市场调查&#xff0c;找出公司生产的牙膏销售量与销售价格&#xff0c;广告投入等之间的关系&#xff0c;从而预测出在不同价格和广告费用下…

多元线性回归检验

多元线性回归模型通常用来研究一个应变量依赖多个自变量的变化关系&#xff0c;如果二者的以来关系可以用线性形式来刻画&#xff0c;则可以建立多元线性模型来进行分析。 1.t检验 t检验是对单个变量系数的显著性检验&#xff0c;一般看p值&#xff1b; 如果p值小于0.05表示该…

[DataAnalysis]多元线性回归深入浅出-案例+模型假设+参数估计方法+模型评判方法+变量选择+多重共线性问题

一、案例介绍 1、目的&#xff1a;利用上市公司当年的公开财务指标预测来年盈利情况最重要的投资人决策依据。 2、数据来源&#xff1a;随机抽取深市和沪市2002和2003年的500个上市公司样本预测来年的净资产收益率。 3、解释变量包括&#xff1a;资产周转率、当年净资产收益…

基于spss的多元回归分析模型

还是数学建模中的一个小问题&#xff0c;具体概念分析在百度上的大佬说的已经足够详细&#xff0c;在此不再赘述。 链接: 多元回归分析. 我主要根据实例讲解如何通过spss进行建模&#xff0c;并进行模型参数的分析和验证。 打开spss&#xff08;如果遇到打不开的情况&#x…

多元线性回归分析预测法概述

在市场的经济活动中&#xff0c;经常会遇到某一市场现象的发展和变化取决于几个影响因素的情况&#xff0c;也就是一个因变量和几个自变量有依存关系的情况。而且有时几个影响因素主次难以区分&#xff0c;或者有的因素虽属次要&#xff0c;但也不能略去其作用。例如&#xff0…

用R进行多元线性回归分析建模

概念&#xff1a;多元回归分析预测法&#xff0c;是指通过对两个或两个以上的自变量与一个因变量的相关分析&#xff0c;建立预测模型进行预测的方法。当自变量与因变量之间存在线性关系时&#xff0c;称为多元线性回归分析。 下面我就举几个例子来说明一下 例一&#xff1a;谋…

基于Python的多元线性回归分析

一、多元线性回归分析&#xff08;Multiple regression&#xff09; 1.与简单线性回归相比较&#xff0c;具有多个自变量x 2.多元回归模型 其中是误差值&#xff0c;与简单线性回归分析中的要求特点相一致。其余的系数和截距为参数。 3.多元回归方程 4.估计多元回归方程(点估…

多元线性回归--案例分析及python实践

回归分析--多元回归 介绍一下多元回归分析中的统计量 总观测值总自变量自由度&#xff1a;回归自由度 &#xff0c;残差自由度 SST总平方和 SSR回归平方和 SSE残差平方和 MSR均方回归 MSE均方残差 判定…

回归分析:多元线性回归模型 白话解析与案例实现

文章目录 线性学习多元线性回归模型多元线性回归模型的python实现 线性学习 回归分析是研究自变量x与因变量y的关系的方法。 上一节我们介绍了一元线性回归&#xff0c;经验公式为&#xff1a; $ \hat{y}\hat{\beta}1 x\hat{\beta}0 $ 在实际生活中&#xff0c;我们要研究的…

多元统计分析——多元线性回归

1. 经典的线性回归分析与交叉验证 examDict{ 学习时 :[0.50, 0.75, 1.00, 1.25,1.50,1.75, 1.75,2.00, 2.25,2.50, 2.75,3.00,3.25,3.50,4.00,4.25,4.50,4.75,5.00,5.50], 分:[10,22,13 ,43,20,22,33,50,62 , 48,55,75,62,73,81,76,64,82,90,93]} examDf pd.DataFrame(examDi…

spss进行多元线性回归并分析表格(转载)

1.如何使用spss进行多元线性回归。 2.分析生成结果&#xff0c;并判断回归是否可行。 一、使用spss进行多元线性回归&#xff1a; 1.输入数据 二、表格结果分析&#xff1a; R方是检验回归是否成功的重要要素之一&#xff0c;DW是残差独立性检验&#xff0c;衡量标准如下&…

数据分析方法--回归分析方法((SPSS建模:多元线性回归案例)

文章目录 回归定义最常用回归方法一、线性回归(Linear Regression)二、逻辑回归(Logistic Regression)三、多项式回归(Polynomial Regression)四、逐步回归(Stepwise Regression)五、岭回归(Ridge Regression)六、套索回归(Lasso Regression)七、回归(ElasticNet) 如何正确选择…