#pragma pack(1)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef short WORD;
typedef unsigned int DWORD;
typedef unsigned char BYTE;
//位图文件头,说明文件类型和位图数据的起始位置??14个字??
typedef struct {
WORD bfType; //文件格式标识2
DWORD bfSize; //整个文件的大??4
WORD bfReserved1; //保留??2
WORD bfReserved2; //保留??2
DWORD bfoffBits; //偏移??4(位图数据前的字节数,非位图数据占的字节??
}BITMAPFILEHEADER;
//位图信息头,说明文件的大小,位图高度和宽??
//位图的颜色格式和压缩类型等信息。共40个字??
typedef struct {
DWORD biSize; //位图信息头占的大??
DWORD biWidth;//文件宽度
DWORD biHeight;//文件高度
WORD biPlane;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage; //图像占的大小
DWORD biXPelsPerMeter;
DWORD biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
}BITMAPINFOHEADER;
//由位图的颜色格式字段所确定的调色板数组
//数组中的每个元素是一个RGBQUAD结构,占4个字节??
typedef struct {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
}RGBQUAD;
//读取文件大小
int getFileSize(char* filename) {
FILE* fp = fopen(filename, "rb");
if (fp == NULL) {
printf("文件不存在\n");
return 0;
}
fseek(fp, 0, SEEK_END);
int length = ftell(fp);
fclose(fp);
return length;
}
//将文件读取到缓冲区中
int LoadInBuf(char* filename, BYTE** buf) {
FILE* fp = fopen(filename, "rb");
if (fp == NULL) {
printf("文件不存在\n");
return 0;
}
int length = getFileSize(filename);
*buf = (BYTE*)malloc(sizeof(BYTE) * length);
fread(*buf, sizeof(BYTE), length, fp);
fclose(fp);
return 1;
}
int SaveInFile(char* filename, BYTE* buf, int size) {
FILE* fp = fopen(filename, "wb");
if (fp == NULL) {
printf("无法创建新的文件\n");
return 0;
}
fwrite(buf, sizeof(BYTE), size, fp);
fclose(fp);
return 1;
}
int main() {
//读取bmp文件,并显示一些基本的信息
char filename[] = "D://CCode//code//位图旋转.bmp";
int length = getFileSize(filename);
BYTE* buf;
LoadInBuf(filename, &buf);
//开辟一个新的缓存区,用于保存转置后的数??
BYTE* buf_copy;
LoadInBuf(filename, &buf_copy);
BITMAPFILEHEADER* fileHeader = (BITMAPFILEHEADER*)buf;
BITMAPINFOHEADER* infoHeader = (BITMAPINFOHEADER*)(buf + sizeof(BITMAPFILEHEADER));
int height = infoHeader->biHeight;
int width = infoHeader->biWidth;
printf("bfSize: %d\n", fileHeader->bfSize);
printf("bfoffBits %d\n", fileHeader->bfoffBits);
printf("位图的大小是%d\n", length);
printf("文件的高度是%d\n", infoHeader->biHeight);
printf("文件的宽度是%d\n", infoHeader->biWidth);
printf("信息头的大小??%d\n", infoHeader->biSize);
printf("biBitCount: %d\n", infoHeader->biBitCount);
printf("biSizeImage: %d\n", infoHeader->biSizeImage);
printf("biXPelsPerMeter: %d\n", infoHeader->biXPelsPerMeter);
printf("biYPelsPerMeter: %d\n", infoHeader->biYPelsPerMeter);
//修改保存文件的信息头的信??
BITMAPINFOHEADER* infoHeader1 = (BITMAPINFOHEADER*)(buf_copy + sizeof(BITMAPFILEHEADER));
BITMAPFILEHEADER* fileHeader1 = (BITMAPFILEHEADER*)buf_copy; infoHeader1->biSizeImage = fileHeader->bfSize - fileHeader->bfoffBits;
//改变图片的高和宽
infoHeader1->biWidth = height;
// infoHeader1->biHeight = -width;
infoHeader1->biHeight = width;
// infoHeader->biWidth = height;
// infoHeader->biHeight = -width;
int addByte = 0;
int addOld = 0;
int addNow = 0;
int imageSize = fileHeader->bfSize - fileHeader->bfoffBits;//文件的总的大小减去头信息和调色??
// //如果每行保存的字节不??4的整数倍,则原来每行是补位了的
// if ((infoHeader->biWidth * infoHeader->biBitCount / 8) % 4 != 0) {
// //需要一共补的字节数
// addByte = (imageSize * 8 - width * height * infoHeader->biBitCount) / 8;
// //原来每行需要补的字??
// addOld = addByte / height;
// }
// //现在每行需要补的字??
// if ((infoHeader->biHeight * infoHeader->biBitCount / 8) % 4 != 0) {
// addNow = (infoHeader->biHeight * infoHeader->biBitCount / 8) % 4;
// //文件大小可能改变,需要修改文件大??
// fileHeader1->bfSize = fileHeader1->bfSize - addByte + addNow * infoHeader->biWidth;
// infoHeader1->biSizeImage = imageSize - addByte + addNow * infoHeader->biWidth;
// }
// else
// {
// //如果不补位,那么文件的大小要修改??
// fileHeader1->bfSize = fileHeader1->bfSize - addByte;
// infoHeader1->biSizeImage = imageSize - addByte;
// }
//将指针指向位图数据区
BYTE* img1 = buf + fileHeader->bfoffBits;//bfoffBit为偏移量
BYTE* img2 = buf_copy + fileHeader1->bfoffBits;
int row_old = width * infoHeader->biBitCount / 8; //以前图像数据每行需要的字节
int row_now = height * infoHeader->biBitCount / 8;//现在图像数据每行需要的字节
int byteOfPixel = infoHeader->biBitCount / 8; //24位真彩色 所以这里应该是24/8=3个字节
//以像素点为单位转置 一个像素点的大小为一个unsigned char 即一个byte-将数据存储基本单位来使用
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int k = 0;
for (; k < byteOfPixel; k++) {
// *(img2 + j * (row_now + addNow) + i*(byteOfPixel) + k) = *(img1 + i * (row_old + addOld) + j*(byteOfPixel) + k);
*(img2 + i * (row_now + addNow) + j*(byteOfPixel) + k)=*(img1 + j * (row_old + addOld)+height*(byteOfPixel) - i*(byteOfPixel) + k);
}
//补位
for (int l = 0; l < addNow; l++) {
*(img2 + j * (row_now + addNow) +row_now + l) = 0x00;
}
}
}
char filename1[] = "D://CCode//code//位图旋转结果.bmp";
SaveInFile(filename1, buf_copy, fileHeader1->bfSize);
free(buf);
free(buf_copy);
system("pause");
return 0;
}
C++位图旋转(顺时针九十度)
于 2022-05-11 09:46:34 首次发布