纯C++实现24位bmp格式图片的读取和修饰
问题:现有一张bmp图片,要求将它读取到程序中并进行灰度化、水平翻转、模糊、茶色滤镜四种效果的一种,并输出新图片,如下所示:
命令行输入:
其中:
参数1:-b/g/s/r,先后表示blur(模糊),grey(灰度化),sepia(褐色),row reverse(水平翻转)
参数2:源文件名
参数3:新文件名
当我第一次接触到这个问题时,是无从下手的。但在查阅了不少资料之后,整整一天,我成功地只用C++实现了打开、修饰、保存bmp文件的功能!
目录
1.bmp文件的基本信息
(1).bmp文件的种类
(2).bmp文件结构(重点)
1>文件头
2>信息头
3>调色板(不作讨论)
4>图像颜色信息
2.实现思路
3.定义相关类、结构体
文件头BmpFileHeader
内存对齐和#pragma pack(n)
信息头BmpFileInfoHeader
颜色结构体RGBTriple
图片类bmp
4.读文件
(1).基础知识
(2).读文件的准备工作
(3).读文件头和数据头
(4).读取图像颜色信息
5.写文件
6.修饰图片
(1).灰度化
(2).棕色滤镜效果
(3).水平翻转
(4).模糊
7.main函数
命令行传参
具体实现
1.bmp文件的基本信息
(1).bmp文件的种类
打开Windows自带的画图软件,发现bmp的存储格式有好几种。
- 单色位图:只有黑白两种颜色,每个像素占1位(1/8字节)
- 16色位图:每个像素占4位(1/2字节)
- 256色位图:每个像素占8位(1字节)
- 24位位图(真彩色):每个像素占24位(3字节),每个字节存储R/G/B三种中的一种颜色数值(0~255)
每个像素占的位数被称为位深度(biBitCount,在后面会用到),可以在图片的属性->详细信息中查看。
(2).bmp文件结构(重点)
bmp文件数据由4部分组成:
- 文件头
- 文件信息头
- 调色板(24位位图无)
- 图像颜色信息
在此只讨论24位位图即真彩色的问题,至于其他的bmp文件种类不做讨论。
先放出图片:
1>文件头
bfType | 如果是bmp文件,值为“BM”,对应十进制为19778 |
bfSize | 文件总大小 |
bfReserved1 | 保留字1,一般为0 |
bfReserved2 | 保留字2,一般为0 |
bfOffBits | 文件起始位置距真正的图像信息的距离 |
2>信息头
biSize | 信息头大小,24位图中为40 |
biWidth | 图像宽度(px),即水平方向的像素个数 |
biHeight | 图像高度(px),即垂直方向的像素个数 |
biPlanes | 一般为1 |
biBitCount | 位深度,重要,决定了bmp的类型 |
biCompression | 是否压缩,一般为0 |
biSizeImages | 图像颜色信息占用的实际字节数,包括了对齐所需的0 |
biXPelsPerMeter | 水平分辨率 |
biYPelsPerMeter | 垂直分辨率 |
biClrUsed | 一般为0 |
biClrImportant | 一般为0 |
注意:我们可能会发现 biWidth*3*biHeight与biSizeImages并不一样,这是为什么呢?接下来会解释。
3>调色板(不作讨论)
4>图像颜色信息
- 像素的存储顺序是从下到上,从左到右,在文件中以类似一维数组的方法线性存储。
- 每个像素的颜色信息每3个字节一组,按BGR的顺序存放。
- 其中每个字节只存一个颜色值。颜色值范围是0~255,用无符号char型存储。
三个图就能说明问题:
但是这些数据真的如此紧密地排列吗?
对于宽为4的倍数的图片(如:1024px),确实如此。每一行的像素数据存完后,紧挨着存储下一行像素的数据,行与行的数据之间没有空隙。
但对于宽度不是4的倍数的图片(如:474px),每一行的像素数据存储完后,会自动空出几个字节,直到这一行的字节数为4的倍数为止。
直接呈上图片:
biWidth=4时:很好,不用补任何0,因为4*3=12已经是4的倍数
biWidth=5时:糟糕,5*3=15不是4的倍数,要补一个0才能是4的倍数16
所以,在读取宽度不是4的倍数的图片时,一行的数据读完后,要跳过几个字节才能读到下一行的数据。跳过字节的个数,我取名为offset。它的计算方法如下:
offset = (fileInFoHeader.biWidth * 3) % 4;
if (offset != 0) {offset = 4 - offset;
}
现在我可以解释2>中末尾提到的问题了。
例子:现在有一张宽度为474px,高度为842px的图片。
不考虑offset时:
474*3*842=1197324(Byte)
考虑时:
(474*3)%4=2
offset=4-2=2(Byte)
每行字节数:474*3+2=1424(Byte)
图像数据总字节数:1424*842=1199008(Byte)
谁对谁错?看看图就知道了。
它们的差值:1199008-1197324= 1684(Byte),而1684=842*2。因为每一行末尾有2字节的空隙,那么,842行的空隙积累起来,正好就是1684字节。
debug的结果说明,图像数据占用的实际字节数是考虑了偏移的,这些数据在存的时候就已经有空隙,因此我们写文件的时候也要刻意的写入空隙,不然系统无法读取我们生成的新图片。这一点在后面很关键!
2.实现思路
首先要把bmp文件读进来。由以上的分析,应该把bmp的文件头、信息头、图像数据分开读取。
然后要生成新bmp文件。应该要依次写入文件头、信息头、图像数据。
最后实现图像处理功能。这些用于图像处理的函数封装在一个单独的头文件中,使用时传入函数指针即可。
3.定义相关类、结构体
定义文件头、信息头结构体(因为它们不需要任何函数),里面存放与文件相关的属性。各个属性的大小参考一开始时的bmp文件结构图,2字节一般定义成unsigned short,4字节一般定义成unsigned int.
定义bmp类(因为它需要定义函数),里面最重要的是一个存放”颜色“结构体对象的数组,用于接收读出的图像颜色数据。还有一个int型的offset,一个文件头结构体对象,一个数据头结构体对象。定义读文件和写文件两个函数。
很自然地,需要一个”颜色“结构体对象,它有三个属性B/G/R。
注意:结构体中,所有属性的定义顺序必须和文件存储的信息顺序一致,否则在读文件时得到的数据会混乱!也就是:必须根据bmp文件结构来!
文件头BmpFileHeader
#pragma pack(2)//注意这里
struct BmpFileHeader {unsigned short bfType;unsigned int bfSize;unsigned short bfReserved1;unsigned short bfReserved2;unsigned int bfOffBits;
};
尤其要注意#pragma pack(2),没有这一行,这个结构体占用的空间大小就不是所有属性大小之和,换句话说,它清除了属性与属性之间内存的”空洞“。明白这个,对读文件操作极其重要!
内存对齐和#pragma pack(n)
在此简短地说一下内存对齐问题,用于测试的代码如下:
#include <iostream>using namespace std;struct BmpFileHeader {unsigned short bfType;unsigned int bfSize;unsigned short bfReserved1;unsigned short bfReserved2;unsigned int bfOffBits;
};int main()
{cout << sizeof(BmpFileHeader)<< endl;//16return 0;
}
但是,这些数据占用的空间按理来说是2+4+2+2+4=14(Byte)才对呀,为什么会输出16呢?
首先放上原理:
结构体的属性是按定义的顺序来存放的。
结构体一般有很多属性,取其中占内存最大的一个,它所占的字节数为默认对齐模数。
假定第一个属性的存放地址为0,后来的数据在存放时,取自身数据大小和对齐模数二者的最小值min,寻找离自己最近的而且是min整数倍的地址,把数据存到那里。
字有点多,不好理解,对不对?还是老规矩,画图:
给这个结构体指定#pragma pack(2)会怎样呢?
#include <iostream>using namespace std;#pragma pack(2)
struct BmpFileHeader {unsigned short bfType;unsigned int bfSize;unsigned short bfReserved1;unsigned short bfReserved2;unsigned int bfOffBits;
};int main()
{cout << sizeof(BmpFileHeader)<< endl;//14return 0;
}
输出14,与我们先前预想的相符。
#pragma pack(n)的作用:为当前结构体指定新的对齐模数n。
信息头BmpFileInfoHeader
struct BmpFileInFoHeader {unsigned int biSize;int biWidth = 0, biHeight = 0;unsigned short biPlanes;unsigned short biBitCount;unsigned int biCompression, biSizeImages;int biXPelsPerMeter, biYPelsPerMeter;unsigned int biClrUsed, biClrImportant;
};
这里不用加#pragma pack()的原因是:这些属性按默认对齐模数4正好可以按顺序无空隙地存储,请大家自行验证。
颜色结构体RGBTriple
它放在一个单独的头文件(RGBTriple.h)中,注意里面的#pragma once,防止头文件重复包含。
也要注意,属性的定义顺序与习惯的不同,它只能是BGR,这是为了使读取时数据存放的顺序正确。
#pragma oncestruct RGBTriple {unsigned char blue;unsigned char green;unsigned char red;
};
图片类bmp
class bmp {
private:int offset;//行尾的空隙RGBTriple* surface;//存图片颜色数据的数组BmpFileHeader fileHeader;//文件头BmpFileInFoHeader fileInFoHeader;//数据头public:void readPic(const char* fileName);//读文件void writePic(void (*myMethod)(int,int,RGBTriple*), const char* outFileName);//写文件
};
surface是一个指针,指向堆中的一个存放着RGBTriple结构体对象的数组。那个数组将在读文件时被创建,并一直保留到程序结束。
读文件和写文件的两个方法可以接收字符串作为文件名。写文件的方法还可以接收一个函数指针,指定在写文件之前,对图片进行的修饰操作。
文件头结构体、信息头结构体、图片类定义在同一个头文件(bmpFile.h)中,完整代码如下:
#pragma once
#include<fstream>
#include<iostream>
#include"RGBTriple.h"
#define BMPTYPE 19778using namespace std;#pragma pack(2)
struct BmpFileHeader {unsigned short bfType;unsigned int bfSize;unsigned short bfReserved1;unsigned short bfReserved2;unsigned int bfOffBits;
};struct BmpFileInFoHeader {unsigned int biSize;int biWidth = 0, biHeight = 0;unsigned short biPlanes;unsigned short biBitCount;unsigned int biCompression, biSizeImages;int biXPelsPerMeter, biYPelsPerMeter;unsigned int biClrUsed, biClrImportant;
};class bmp {
private:int offset;RGBTriple* surface;BmpFileHeader fileHeader;BmpFileInFoHeader fileInFoHeader;public:void readPic(const char* fileName);void writePic(void (*myMethod)(int,int,RGBTriple*), const char* outFileName);
};
4.读文件
(1).基础知识
C++的fstream头文件提供了文件输入流ifstream和文件输出流ofstream。
两种流对象在使用时有一些相同的步骤:
- 创建流对象
- 打开文件:open(“文件路径”,打开方式)
- (可选)检测文件是否打开:is_open()
- 使用后关闭流:close()
常见的打开方式:
ios::in | 读文件 |
ios::out | 写文件 |
ios::app | 打开文件时,光标在文件末尾 |
ios::trunc | 如果存在同名文件,就删除它创建新文件 |
ios::binary | 以二进制的方式读/写文件 |
几个不同的打开方式可以用 |(单竖线)连接,表示这种打开方式同时具有两种含义。
一个完整的使用ifstream的例子:
#include<fstream>
#include<iostream>using namespace std;int main(){ifstream ifs;ifs.open("aaa.bmp",ios::in | ios::binary);if(!ifs.is_open()){cout<<"文件未打开!"<<endl;}//读取...ifs.close();
}
ifstream的特有方法:read();ofstream的特有方法:write();它们的函数原型如下:
basic_istream& __CLR_OR_THIS_CALL read(_Elem* _Str, streamsize _Count);
参数1:char*类型,表示待读入的数据的“去路”
参数2:一次读入数据的字节总数
basic_ostream& __CLR_OR_THIS_CALL write(const _Elem* _Str, streamsize _Count);
参数1:char*类型,表示待写入的数据的来源
参数2:一次写入数据的字节总数
(2).读文件的准备工作
新建bmpFile.cpp文件,书写bmp类两个函数的空实现。
#include"bmpFile.h"void bmp::readPic(const char* fileName) {}void bmp::writePic(void (*myMethod)(int,int,RGBTriple*),const char* outFileName) {}
注意到bmpFile.h中已经引入了头文件fsteram,故直接使用其中的结构即可。
#include"bmpFile.h"void bmp::readPic(const char* fileName) {ifstream ifs;ifs.open(fileName, ios::in|ios::binary);if (!ifs.is_open()) {cout << "Can't open the file." << endl;return;}//do somethingifs.close();
}void bmp::writePic(void (*myMethod)(int,int,RGBTriple*),const char* outFileName) {}
注意ios::binary,它指定以二进制的方式读文件,如果少了它,程序虽不出错,但输出的图片却是一团黑(亲测)。
(3).读文件头和数据头
按先前的思路来,先读文件头,再读数据头,剩下的就是图像信息了。
ifs.read((char*)&fileHeader,sizeof(BmpFileHeader));
注意里面的强制类型转换。之所以把fileHeader结构体对象的地址转换成char*型,就是因为read()函数只接收char*型的地址。
读完文件头之后,有个问题:要是读进来的文件根本不是bmp类型怎么办?那么后面的操作不就失去意义了吗?
所以我们紧接着添加一个if语句来判断读的是不是bmp类型,如果不是,就结束整个函数。由bmp文件头结构可知,其中的bfType如果不是19778,文件就不是bmp类型。19778已经在bmpFile.h中被定义为宏常量BMPTYPE。
if(fileHeader.bfType!=BMPTYPE){cout<<"文件类型不正确!"<<endl;return;
}
接着才读取数据头。还是一样的问题,读的bmp文件不是24位的怎么办?非24位的bmp,我们是不能处理的,只能再加上一个判断,如果不是24位就结束整个函数。
ifs.read((char*)&fileInFoHeader, sizeof(BmpFileInFoHeader));if (fileInFoHeader.biBitCount != 24) {cout << "invalid!" << endl; return;
}
(4).读取图像颜色信息
现在终于可以开始读取图像颜色信息啦!但在此之前,我们要解决空隙的问题。在读取数据头之后,我们获得了图像宽度biWidth,这时才可以计算offset的大小。
offset = (fileInFoHeader.biWidth * 3) % 4;
if (offset != 0) {offset = 4 - offset;
}
还要考虑一个问题:我们必须使用一个存放RGBTriple对象的数组来存整张图片的颜色信息。
这个问题可以分解成两个小问题:
Q1:存在栈里还是存在堆里?
答案显而易见,一般图片的长宽在1000px以上的不在少数,如果存在栈里,栈很可能会溢出。
Q2:定义一维数组还是二维数组?
我们很自然地会想用二维数组,因为图片就是按行、列存储的。但实际上不行,因为尽管new是动态分配内存,二维数组的第二维仍然必须是一个常量,否则new不知道应该返回什么类型的行指针(有关这方面的知识,可以参考其他文章),编译会报错。我们可以用一种“降维”的方法解决这个问题,就是new一个超长的一维数组,它的长度是图片的(长*宽)。
用于存放图像颜色数据的数组surface是一个RGBTriple型的指针。我们new一个新的一维数组,将数组首地址赋给surface。
surface = new RGBTriple[fileInFoHeader.biHeight * fileInFoHeader.biWidth];
到目前为止,我们终于可以开始读bmp文件中最重要的信息啦!
还记得吗?bmp文件的像素存储顺序:从下到上,从左到右。因此我们如果要想在surface存入正常顺序的像素数据(从上到下,从左到右),在向surface中存数据时就有讲究,先读出的像素数据要靠后存储。
一次读入3个字节(BGR),存入surface的某一元素(即:一个RGBTriple对象)中。
这里说句题外话,我遇到过这样一个问题:我一开始为RGBTriple定义了无参、有参构造函数,可以用B、G、R三个参数创建新的RGBTriple对象。接着写了这些代码:
for (int i = fileInFoHeader.biHeight-1;i >=0;i--) {int ured=0,ublue=0,ugreen=0;for (int j = 0;j < fileInFoHeader.biWidth;j++) {ifs.read((char*)(&ured), sizeof(char)); ifs.read((char*)(&ugreen), sizeof(char)); ifs.read((char*)(&ublue), sizeof(char)); RGBTriple rgb(ublue,ugreen,ured);*(surface+(fileInFoHeader.biWidth * i + j))=rgb;}if (offset != 0) {char ign;for (int k = 0;k < offset;k++) {ifs.read(&ign,sizeof(char));}}}
这是一个不太好发现的错误,细心的小伙伴可能已经看出,红色与蓝色的读取顺序反了。这导致输出图片的颜色整体有些偏差,就像这样(我其实也可以把它叫做艺术品?):
题外话结束...
我们直接一次性地从文件中读出3个字节,存入surface数组的某个元素中。
for (int i = fileInFoHeader.biHeight-1;i >=0;i--) {for (int j = 0;j < fileInFoHeader.biWidth;j++) {ifs.read((char*)(surface+(fileInFoHeader.biWidth * i + j)), sizeof(RGBTriple)); }if (offset != 0) {char ign;for (int k = 0;k < offset;k++) {ifs.read(&ign,sizeof(char));}}}
内层for循环结束代表一行像素读取完毕,此时就要注意空隙问题了。有空隙时,必须跳过空隙。如何跳过空隙呢?定义一个临时变量ign(ignore的简写),把offset个字符循环读入ign,最终ign被丢弃。这样就把用于补齐的0读走了,再读取下一行时,读取文件的指针就已经指到了真正的数据上。
完整代码如下:
void bmp::readPic(const char* fileName) {ifstream ifs;ifs.open(fileName, ios::in|ios::binary);if (!ifs.is_open()) {cout << "Can't open the file." << endl;return;}ifs.read((char*)&fileHeader, sizeof(BmpFileHeader));if (fileHeader.bfType != BMPTYPE) {cout << "type error!" << endl;return;}ifs.read((char*)&fileInFoHeader, sizeof(BmpFileInFoHeader));if (fileInFoHeader.biBitCount != 24) {cout << "invalid!" << endl; return;}offset = (fileInFoHeader.biWidth * 3) % 4;if (offset != 0) {offset = 4 - offset;}surface = new RGBTriple[fileInFoHeader.biHeight * fileInFoHeader.biWidth];for (int i = fileInFoHeader.biHeight-1;i >=0;i--) {for (int j = 0;j < fileInFoHeader.biWidth;j++) {ifs.read((char*)(surface+(fileInFoHeader.biWidth * i + j)), sizeof(RGBTriple)); }if (offset != 0) {char ign;for (int k = 0;k < offset;k++) {ifs.read(&ign,sizeof(char));}}}ifs.close();
}
5.写文件
写文件比读文件容易,需要使用ofstream对象的write()函数。
用于图像修饰的函数(myMethod)是由函数指针传入的,这个函数指针的类型是:返回值void;参数列表:int height,int width,RGBTriple* (实质上是数组的首地址)。
接下来的操作和读文件大致相同,只是有几个注意点:
- open()时必须写ios::binary,否则也会产生错误。这种错误与读文件时又不同了,并不是输出乌黑的图片,而是有一种别样的颜色滤镜效果。摆出图片(不得不说,还挺有艺术感?):
- 从surface的height-1索引开始取出数据用于写入。因为我们读文件时,height-1这里存放的是左下角的像素,我们也应该从左下角的像素开始写才能输出正向的图片。
- 写完文件之后,surface数组完成了它的使命,应该被delete掉。因为new的是一个数组,所以应该使用delete[],以完全释放内存。
完整代码如下:
void bmp::writePic(void (*myMethod)(int,int,RGBTriple*),const char* outFileName) {//modifymyMethod(fileInFoHeader.biHeight, fileInFoHeader.biWidth, surface);//create a new bmpofstream ofs;ofs.open(outFileName, ios::out|ios::binary);ofs.write((char*)&fileHeader, sizeof(BmpFileHeader));ofs.write((char*)&fileInFoHeader, sizeof(BmpFileInFoHeader));//rewritefor (int i = fileInFoHeader.biHeight - 1;i >= 0;i--) {for (int j = 0;j < fileInFoHeader.biWidth;j++) {ofs.write((char*)(surface + (i*fileInFoHeader.biWidth+j)), sizeof(RGBTriple));}if (offset != 0) {char ign=0;for (int k = 0;k < offset;k++) {ofs.write(&ign, sizeof(char));}}}delete[] surface;ofs.close();
}
6.修饰图片
本质上是对当前对象里的surface数组进行原地修改。
新建一个头文件helpers.h,给出了四个函数的声明。新建源程序文件helpers.cpp提供函数实现。
helpers.h的结构:
#pragma once
#include<iostream>
#include"RGBTriple.h"using namespace std;void makeGray(int height , int width , RGBTriple* image);
void makeSpeia(int height, int width, RGBTriple* image);
void rowReverse(int height, int width, RGBTriple* image);
void makeBlur(int height, int width, RGBTriple* image);
helpers.cpp的结构:
#include"helpers.h"using namespace std;void makeGray(int height, int width, RGBTriple* image) {}
void makeSpeia(int height, int width, RGBTriple* image) {}
void rowReverse(int height, int width, RGBTriple* image) {}void makeBlur(int height, int width, RGBTriple* image) {}
(1).灰度化
原理:取出每个像素的RGB值,三个值求平均数,再将平均数分别赋值给RGB。
void makeGray(int height, int width, RGBTriple* image) {for (int i = 0;i < height;i++) {for (int j = 0;j < width;j++) {int aver = ((image+(i * width + j))->blue+ (image + (i * width + j))->green+ (image + (i * width + j))->red)/3;(image + (i * width + j))->blue = (image + (i * width + j))->green = (image + (i * width + j))->red = aver;}}
}
这个函数的实现相对容易。
(2).棕色滤镜效果
原理:公式
新Red=原Red*0.393+原Green*0.769+原Blue*0.189;
新Green=原Red*0.349+原Green*0.686+原Blue*0.168;
新Blue=原Red*0.272+原Green*0.534+原Blue*0.131;
这里,隐藏着一个很大的bug!
大家发现,如果对一个白色像素进行操作(255,255,255),会得到(344,306,238),三个颜色值有两个都已经溢出!
因此需要这么一个逻辑:当检测到算出的颜色值溢出时,将它重新设置成255.
void makeSpeia(int height, int width, RGBTriple* image) {int ured = 0 , ugreen=0 , ublue=0;for (int i = 0;i < height;i++) {for (int j = 0;j < width;j++) {ured = ((image + (i * width + j))->red) * 0.393 + ((image + (i * width + j))->green) * 0.769 + ((image + (i * width + j))->blue) * 0.189;ugreen = ((image + (i * width + j))->red) * 0.349 + ((image + (i * width + j))->green) * 0.686 + ((image + (i * width + j))->blue) * 0.168;ublue = ((image + (i * width + j))->red) * 0.272 + ((image + (i * width + j))->green) * 0.534 + ((image + (i * width + j))->blue) * 0.131;if (ured > 255) {ured = 255;}if (ugreen > 255) {ugreen = 255;}if (ublue > 255) {ublue = 255;}(image + (i * width + j))->red = ured;(image + (i * width + j))->green = ugreen;(image + (i * width + j))->blue = ublue;ured = ugreen = ublue = 0;}}
}
(3).水平翻转
原理:外层for遍历每一行,内层for在行的开头和结尾定义两个计数变量,这两个变量同时向行中心移动,直至它们相等或“错过”,在每次移动时,交换两个变量对应像素的R、G、B三个值。
void rowReverse(int height, int width, RGBTriple* image) {int ured = 0, ugreen = 0, ublue = 0;for (int i = 0;i < height;i++) {for (int j = 0,k=width-1;j < k;j++,k--) {ured = (image + (i * width + j))->red;(image + (i * width + j))->red = (image + (i * width + k))->red;(image + (i * width + k))->red = ured;ugreen = (image + (i * width + j))->green;(image + (i * width + j))->green = (image + (i * width + k))->green;(image + (i * width + k))->green = ugreen;ublue = (image + (i * width + j))->blue;(image + (i * width + j))->blue = (image + (i * width + k))->blue;(image + (i * width + k))->blue = ublue;}}
}
(4).模糊
原理:
我们对每一个像素进行如此操作之后,每一个像素都对应了自己的一份崭新的RGB颜色值。得到所有新颜色值之后,用它们依次覆盖掉原来的图片数据。
最终处理后的图片如下:
实现上的几个难点:
- 必须用一个临时数组(肯定也在堆中,不然放不下)把新的颜色值存起来,等所有的像素都运算完了,再把临时数组中的值统一赋给原数组。否则,新的颜色值的输入会影响临近几个像素的运算,产生“污染”。统一赋值结束后,记得把临时数组delete掉。
- 如何确定3*3网格到底盖住了几个像素? 先将目光放在中心格子的左上角那个格子,即image[i-1][j-1],然后看看 i-1 和 j-1 是否越界。本质上说,这两层for循环扫描了包括了中心格子在内的9个格子,并统计了有效(在图片范围内)的格子数。
以下为完整代码:
void makeBlur(int height, int width, RGBTriple* image) {RGBTriple* temp = new RGBTriple[height * width]();int ured = 0, ugreen=0, ublue = 0;for (int i = 0;i < height;i++) {for (int j = 0;j < width;j++) {//计算实际覆盖的像素数量int total = 0;for (int y = i - 1, myCount = 0;myCount < 3;y++,myCount++) {if (y >= 0 && y < height) {for (int x = j - 1, myCount1 = 0;myCount1 < 3;x++, myCount1++) {if (x >= 0 && x < width) {ured+= (image + (y * width + x))->red;ugreen += (image + (y * width + x))->green;ublue += (image + (y * width + x))->blue;total++;}}}}(temp + (i * width + j))->red=(ured/total);(temp + (i * width + j))->green = (ugreen / total);(temp + (i * width + j))->blue = (ublue / total);ured = ugreen = ublue = 0;}}for (int i = 0;i < height;i++) {for (int j = 0;j < width;j++) {(image + (i * width + j))->blue = (temp + (i * width + j))->blue;(image + (i * width + j))->green = (temp + (i * width + j))->green;(image + (i * width + j))->red = (temp + (i * width + j))->red;}}delete[] temp;
}
7.main函数
我们最后回到一开始的命令行窗口这里:
可以看出,main函数接收了三个参数,分别为:对图片的修饰方法、原文件名、新文件名
命令行传参
int main(int argc,char* argv[]){//do something
}
argc:参数总个数
argv:字符串数组,各个元素之间用任意个空白字符隔开
argv[0]是不能被直接读取的,真正的参数从argv[1]开始依次向后存放。
具体实现
#include <iostream>
#include<cstring>
#include"bmpFile.h"
#include"helpers.h"using namespace std;int main(int argc,const char* argv[])
{for (int i = 1;i < argc;i++) {cout << argv[i]<<" ";}bmp mybmp;mybmp.readPic(argv[2]);if (!strcmp(argv[1],"-g")) {mybmp.writePic(makeGray,argv[3]);}else if (!strcmp(argv[1], "-s")) {mybmp.writePic(makeSpeia, argv[3]);}else if (!strcmp(argv[1], "-b")) {mybmp.writePic(makeBlur, argv[3]);}else if (!strcmp(argv[1], "-r")) {mybmp.writePic(rowReverse, argv[3]);}else {cout << "failed to write!" << endl;}return 0;
}
几个注意点:
- 因为main.cpp中同时包含了helpers.h和bmpFile.h,而它们俩都包含了RGBTriple.h,所以,必须在RGBTriple.h中加上#pragma once,否则链接会出错;
- 不要用==去判断两个字符串是否相等,因为这只会比较地址值,这里必须用strcmp()函数。
小结:
哈,终于写完了!这个案例可以帮我们回顾不少学过的知识点,比如指针的运算、文件流的操作、函数指针、命令行传参等,也帮助我了解了不少新知识,如bmp文件的格式和内部存储方式、内存对齐、fstream的read()和write()方法等。
加油,代码人!
部分参考自:
#Pragma Pack(n)与内存分配 pragma pack(push,1)与#pragma pack(1)的区别_Wanda && Aidem -CSDN博客
BMP格式详解_Tut-CSDN博客_bmp格式
BMP文件格式详解(BMP file format)_mjiansun的专栏-CSDN博客_bmp文件格式
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- Android开发三年,面了八家公司终于腾讯上岸,含泪整理面经
10.双缓冲机制。 11.丢帧的原因。 12.帧数计算。 13.设计如何检测过度绘制的工具,要具体到view。 14.blockcanary原理,目的。 15.listview的滑动优化,比如一个kmoji可以用textview渲染,也可以用imageview渲染,哪个…...
2024/4/14 23:13:38 - 2021CCPC中国大学生程序设计竞赛女生专场 G. 3G网络
题目链接 题目描述 解题思路 当 r->∞ 时,圆相当于几乎重合,所以答案是1/n 代码 #include<iostream> #include<stdio.h> #include<vector> #include<string> #include<algorithm> #include<map> #include<…...
2024/5/5 4:23:50 - 如何使用vue-cli搭建SPA项目
目标: 通过vue-cli脚手架构建SPA项目 将index.html与组件分开 嵌套路由 一,什么是vue-cli vue-cli是vue.js的脚手架,用于自动生成vue.jswebpack的项目模板,创建命令如下: vue init webpack xxx …...
2024/4/14 23:13:18 - yxc_第一章 基础算法(一)
一、快速排序 1.零散知识点 (1)swap()函数: C标准库函数,可以交换两个变量的值。包括:整数,字符串,数组,以及栈等数组结构。 swap函数详细解释 c内置了sw…...
2024/4/24 17:42:23 - 二层与三层交换机我知道,四层交换机是什么东西
前言: 随着百兆、千兆以及万兆局域网的普及和宽带城域网以及宽带广域网的广泛应用,不管是内联网、外联网、还是小区智能网,日益扩张的信息量,正迫使着人们对网络系统中的音频、视频、数据等信息的传输量要求越来越高。基于此&…...
2024/4/14 23:13:38 - Python学生成绩管理
3、实验题目:学生成绩管理 将学生对象存入列表中,并按成绩对学生进行排序,并获取成绩最高和成绩最低的学生信息,并将最高分和最低分的学生从列表删除,最后再对列表进行拷贝,对拷贝的列表进行翻转输出。 import copy …...
2024/4/14 23:13:23 - 【剑指Offer打卡】30.包含min函数的栈
剑指 Offer 30. 包含min函数的栈 JavaScript剑指Offer题解 🚀包含数组、对象、链表、堆栈、树等经典题型 ☕️每天一道,轻松不累 💬详细的题目解析,收藏方便阅读 🙏在线star地址 在线阅读地址 在线阅读地址 题目描述…...
2024/4/14 23:13:43 - macOS修改hosts
编辑/etc/hosts sudo vim /etc/hosts示例: 127.0.0.1 www.xxxx.com...
2024/4/18 9:17:10 - 使用 mybatis plus 实现创建和修改数据时自动修改时间
引入相关依赖 <!--MybatisPlus--> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.1</version> </dependency> <!--MySQL--> <dependency>…...
2024/4/19 16:07:41 - 学习ECMAScript 2015【2】Classes
0. 前言 其实类这个概念,最早在C出现,Java发扬光大。JS之前也写类,根据文章:JavaScript 定义类的最佳写法——完整支持面向对象(封装、继承、多态),兼容所有浏览器,支持用JSDuck生成…...
2024/4/18 13:33:04 - “二十一天好习惯”第一期-14
这是今天在做题时遇到的问题,选择语句中不能和0进行比较。需要定义一个常变量#define g 1e-6,然后再使需要比较的值和g进行比较。如d<g就是d<0,d>g就是d>0,其他情况就是d0。 这个g表示一个极小的数,可以看做0。 还有…...
2024/4/19 9:41:10 - 【AcWing】788.逆序对的数量
题目描述: 给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。 逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。 输入格式 …...
2024/4/14 23:13:13 - 2019年试题
目录 一、程序阅读与理解。(45分) 二、简答题(60分) 三、算法设计(45分) 一、程序阅读与理解。(45分) 1、 #include <stdio.h> int main() {int count 5;while (count &l…...
2024/4/14 23:13:43 - 遗传算法的神经网络python实现源码
代码过程中,把代码过程较好的一些代码段记录起来,下边代码是关于遗传算法的神经网络python实现的代码,应该对大伙有一些用处。 from operator import itemgetter, attrgetter import math import random import string import timeit from t…...
2024/4/14 23:13:08 - 设计模式篇01~~~单例
设计模式篇01~单例 1.关系类图 2.单例介绍 定义:指一个类只有一个实例,且能自行创建这个实例的一种模式.例如,windows中只能打开一个任务管理器,这样可以避免因打开多个任务管理器而造成内存资源浪费,而出现各个窗口显示内容的不一致错误.单例模式特点:1)单例只有一个实例对象…...
2024/4/14 23:14:19 - 【PTA乙级】1013.数素数
题目描述: 令Pi表示第 i 个素数。现任给两个正整数 M≤N≤10^4,请输出PM到PN的所有素数。 输入格式 输入在一行中给出 M 和 N,其间以空格分隔。 输出格式 输出从PM到PN的所有素数,每 10 个数字占 1 行,其…...
2024/4/14 23:14:24 - SpringCloud H版系列10--Bus消息中心
Bus消息中心一、Spring Cloud Bus1.1Bus 解决的问题1.2刷新类型介绍1.3 Bus消息中心原理和思想二、搭建RabbitMQ三、参照3355模块新建3366模块四、测试书接上文,继续跟着周阳老师学习SpringCloud的消息中心Bus。 一、Spring Cloud Bus Spring Cloud Bus 集成了市面…...
2024/4/18 17:13:23 - 2021CCPC中国大学生程序设计竞赛女生专场 K 音乐游戏
题目链接 题目描述 解题思路 这是一个签到题,只要统计_的个数就行了 代码: #include<iostream> #include<stdio.h> #include<vector> #include<string> #include<algorithm> #include<map> #include<queue&g…...
2024/4/27 0:15:01 - 【python pandas excel操作】
目录 1、打开Excel,获取不同sheet的名称 2、获取不同sheet的内容 3、 获取行数以及表头 4、对某一列的信息进行筛选 5、其他panda对Excel的操作 摘自:python对excel操作获取某一列,某一行的值,对某一列信息筛选_春风若是你的博…...
2024/4/18 10:27:47 - 婚前个人债务在婚姻关系存续期间怎么负担
《最高人民法院民法典婚姻家庭编司法解释(一)》第三十三条 债权人就一方婚前所负个人债务向债务人的配偶主张权利的,人民法院不予支持。但债权人能够证明所负债务用于婚后家庭共同生活的除外。 【审判实践中应注意的问题】 一、债权人就一…...
2024/4/14 23:14:24
最新文章
- Rust web简单实战
一、使用async搭建简单的web服务 1、修改cargo.toml文件添加依赖 [dependencies] futures "0.3" tokio { version "1", features ["full"] } [dependencies.async-std] version "1.6" features ["attributes"]2、搭…...
2024/5/5 13:50:13 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 如何转行成为产品经理?
转行NPDP也是很合适的一条发展路径,之后从事新产品开发相关工作~ 一、什么是NPDP? NPDP 是产品经理国际资格认证,美国产品开发与管理协会(PDMA)发起的,是目前国际公认的唯一的新产品开发专业认证ÿ…...
2024/5/4 23:56:47 - 【C++】C++中的list
一、介绍 官方给的 list的文档介绍 简单来说就是: list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中…...
2024/5/5 8:49:36 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/4 23:54:56 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/4 23:54:56 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/4 23:55:17 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/4 23:55:16 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/4 18:20:48 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/4 23:55:17 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/4 23:55:06 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/4 23:55:06 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/4 23:55:16 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/4 23:55:01 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/4 23:54:56 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57