用C语言编写一个程序,完成实验要求
时间: 2024-11-12 20:39:03 浏览: 7
为了完成《实验5:图像旋转作业要求》的任务,你需要编写一个C语言程序来实现BMP图像的90度顺时针或逆时针旋转。以下是一个详细的步骤和示例代码:
### 步骤
1. **读取BMP文件头和DIB头**:
- 打开BMP文件并读取文件头(`BITMAPFILEHEADER`)和DIB头(`BITMAPINFOHEADER`)。
- 检查文件是否为8位(256色)的调色板图像。
2. **读取调色板**:
- 读取调色板数据。
3. **读取图像数据**:
- 根据图像的高度和宽度,读取图像的像素数据。
4. **计算旋转后的图像尺寸**:
- 计算旋转后的图像高度和宽度。
5. **创建新的BMP文件**:
- 创建一个新的BMP文件,并写入新的文件头和DIB头。
- 写入新的调色板数据。
6. **旋转图像数据**:
- 根据旋转方向(顺时针或逆时针),重新排列像素数据。
7. **写入旋转后的图像数据**:
- 将旋转后的像素数据写入新文件。
8. **输出相关信息**:
- 显示旋转前后的文件大小、偏移、图像宽度、高度、位深和调色板。
### 示例代码
```c
#include <stdio.h>
#include <stdlib.h>
#pragma pack(1)
typedef struct {
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} BITMAPFILEHEADER;
typedef struct {
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BITMAPINFOHEADER;
void rotateBMP(const char* inputPath, const char* outputPath, int direction) {
FILE *inFile = fopen(inputPath, "rb");
if (!inFile) {
perror("无法打开输入文件");
return;
}
BITMAPFILEHEADER fileHeader;
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, inFile);
BITMAPINFOHEADER infoHeader;
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, inFile);
if (infoHeader.biBitCount != 8) {
fprintf(stderr, "仅支持8位BMP图像\n");
fclose(inFile);
return;
}
// 读取调色板
RGBQUAD palette[256];
fread(palette, sizeof(RGBQUAD), 256, inFile);
// 读取图像数据
int width = infoHeader.biWidth;
int height = infoHeader.biHeight;
int padding = (4 - (width % 4)) % 4; // BMP格式每行字节数必须是4的倍数
unsigned char *imageData = (unsigned char *)malloc(height * (width + padding));
fread(imageData, 1, height * (width + padding), inFile);
fclose(inFile);
// 创建新的BMP文件
FILE *outFile = fopen(outputPath, "wb");
if (!outFile) {
perror("无法打开输出文件");
free(imageData);
return;
}
// 更新文件头和DIB头
BITMAPFILEHEADER newFileHeader = fileHeader;
BITMAPINFOHEADER newInfoHeader = infoHeader;
if (direction == 1) { // 顺时针90度
newInfoHeader.biWidth = height;
newInfoHeader.biHeight = width;
} else if (direction == -1) { // 逆时针90度
newInfoHeader.biWidth = height;
newInfoHeader.biHeight = -width; // 负值表示自下而上的顺序
} else {
fprintf(stderr, "无效的方向\n");
free(imageData);
fclose(outFile);
return;
}
newFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
newInfoHeader.biSizeImage = newInfoHeader.biWidth * abs(newInfoHeader.biHeight);
fwrite(&newFileHeader, sizeof(BITMAPFILEHEADER), 1, outFile);
fwrite(&newInfoHeader, sizeof(BITMAPINFOHEADER), 1, outFile);
fwrite(palette, sizeof(RGBQUAD), 256, outFile);
// 旋转图像数据
unsigned char *rotatedImageData = (unsigned char *)malloc(newInfoHeader.biWidth * abs(newInfoHeader.biHeight));
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
int srcIndex = y * (width + padding) + x;
int dstX, dstY;
if (direction == 1) { // 顺时针90度
dstX = height - y - 1;
dstY = x;
} else if (direction == -1) { // 逆时针90度
dstX = y;
dstY = width - x - 1;
}
int dstIndex = dstY * newInfoHeader.biWidth + dstX;
rotatedImageData[dstIndex] = imageData[srcIndex];
}
}
// 写入旋转后的图像数据
fwrite(rotatedImageData, 1, newInfoHeader.biSizeImage, outFile);
// 关闭文件
fclose(outFile);
free(imageData);
free(rotatedImageData);
// 输出相关信息
printf("文件大小: %d\n", newFileHeader.bfSize);
printf("偏移: %d\n", newFileHeader.bfOffBits);
printf("图像宽度: %d\n", newInfoHeader.biWidth);
printf("图像高度: %d\n", newInfoHeader.biHeight);
printf("位深: %d\n", newInfoHeader.biBitCount);
printf("调色板: %d\n", newInfoHeader.biPlanes);
}
int main() {
const char *inputPath = "input.bmp";
const char *outputPath = "output.bmp";
int direction = 1; // 1 表示顺时针90度,-1 表示逆时针90度
rotateBMP(inputPath, outputPath, direction);
return 0;
}
```
### 说明
- `rotateBMP` 函数实现了图像的读取、旋转和写入。
- `main` 函数调用了 `rotateBMP` 并指定了输入文件路径、输出文件路径和旋转方向。
- 旋转方向通过 `direction` 参数控制,1 表示顺时针90度,-1 表示逆时针90度。
希望这个示例代码能帮助你完成实验任务。如果有任何问题,请随时提问。
阅读全文