#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma pack(1) /* 必須在結構體定義之前使用,這是為了讓結構體中各成員按1位元組對齊*/
typedef struct tagBITMAPFILEHEADER
{
unsigned short bfType; // 儲存圖片型別。 'BM'
unsigned long bfSize; // 點陣圖檔案的大小,以位元組為單位(3-6位元組,低位在前)
unsigned short bfReserved1; // 點陣圖檔案保留字,必須為0(7-8位元組)
unsigned short bfReserved2; // 點陣圖檔案保留字,必須為0(9-10位元組)
unsigned long bfOffBits; // RGB資料偏移地址,點陣圖資料的起始位置,以相對於點陣圖(11-14位元組,低位在前)
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
unsigned long biSize; // 本結構所佔用位元組數(15-18位元組)
unsigned long biWidth; // 點陣圖的寬度,以畫素為單位(19-22位元組)
unsigned long biHeight; // 點陣圖的高度,以畫素為單位(23-26位元組)
unsigned short biPlanes; // 目標裝置的級別,必須為1(27-28位元組)
unsigned short biBitCount; // 每個畫素所需的位數,必須是1(雙色)(29-30位元組),4(16色),8(256色)16(高彩色)或24(真彩色)之一
unsigned long biCompression; // 點陣圖壓縮型別,必須是0(不壓縮),(31-34位元組)
// 1(BI_RLE8壓縮型別)或2(BI_RLE4壓縮型別)之一
unsigned long biSizeImage; // 點陣圖的大小(其中包含了為了補齊行數是4的倍數而新增的空位元組),以位元組為單位(35-38位元組)
unsigned long biXPelsPerMeter; // 點陣圖水平解析度,每米畫素數(39-42位元組)
unsigned long biYPelsPerMeter; // 點陣圖垂直解析度,每米畫素數(43-46位元組)
unsigned long biClrUsed; // 點陣圖實際使用的顏色表中的顏色數(47-50位元組)
unsigned long biClrImportant; // 點陣圖顯示過程中重要的顏色數(51-54位元組)
} BITMAPINFOHEADER;
#pragma pack()
// 取消位元組對齊
/*
函式名稱:Bmp_Smaller
函式功能:圖片放大縮小
引數:BITMAPFILEHEADER head,BITMAPINFOHEADER info-原照片頭資訊
返回值:void
*/
void Bmp_Bigger_And_Smaller(char *path)
{
FILE *fpr1 = fopen(path, "rb");
FILE *fpw2 = fopen("new.bmp", "wb");
if (fpr1 == NULL || fpw2 == NULL)
{
printf("圖片開啟失敗!\n");
return;
}
// 讀取原照片的頭資訊
struct tagBITMAPFILEHEADER head;
struct tagBITMAPINFOHEADER info;
fread(&head, sizeof(BITMAPFILEHEADER), 1, fpr1);
fread(&info, sizeof(BITMAPINFOHEADER), 1, fpr1);
unsigned int old_width = info.biWidth; // 獲取原圖片的寬
unsigned int old_height = info.biHeight; // 獲取原圖片的高
// 獲取原圖片的點陣圖資料
unsigned char *src_data = malloc(old_width * old_height * 3);
fseek(fpr1, 54, SEEK_SET);
fread(src_data, old_width * old_height * 3, 1, fpr1);
printf("原圖片的寬:%d\n", old_width);
printf("原圖片的高:%d\n", old_height);
// 修改原照片的寬高
unsigned int new_Width, new_Height;
printf("請輸入新圖片的寬:\n");
scanf("%d", &new_Width);
printf("請輸入新圖片的高:\n");
scanf("%d", &new_Height);
int ret = (4 - new_Width * 3 % 4) % 4;
head.bfSize = new_Width * new_Height * 3 + 54 + ret * new_Width;
info.biSizeImage = new_Width * new_Height * 3 + ret * new_Width;
info.biWidth = new_Width;
info.biHeight = new_Height;
// 將修改過的頭資訊寫進新照片
fwrite(&head, sizeof(BITMAPFILEHEADER), 1, fpw2);
fwrite(&info, sizeof(BITMAPINFOHEADER), 1, fpw2);
int i = 0, j = 0;
unsigned long dwsrcX, dwsrcY; // 新bmp畫素點對應的原bmp畫素點位置
unsigned char *pucDest; // 新bmp行數對應的起始畫素點
unsigned char *pucSrc; // 原bmp畫素點
unsigned char *dest_data = malloc(new_Width * new_Height * 3 + ret * new_Width); // 新bmp畫素空間大小
for (i = 0; i < new_Height; i++)
{
dwsrcY = i * old_height / new_Height;
pucDest = dest_data + i * new_Width * 3;
pucSrc = src_data + dwsrcY * old_width * 3;
for (j = 0; j < new_Width; j++)
{
dwsrcX = j * old_width / new_Width;
memcpy(pucDest + j * 3, pucSrc + dwsrcX * 3 + ret * i, 3); // 資料複製
}
}
fseek(fpw2, 54, SEEK_SET);
fwrite(dest_data, new_Width * new_Height * 3, 1, fpw2);
printf("生成新圖片成功!\n");
// 釋放堆空間
free(dest_data);
free(src_data);
// 關閉檔案
fclose(fpr1);
fclose(fpw2);
}
/*
函式名稱:main
函式功能:主函式
引數:void
返回值:int
*/
int main(int argc, char const *argv[])
{
Bmp_Bigger_And_Smaller(argv[1]);
return 0;
}
測試結果