近期碰到了一个问题将图片缩放:
进行了整理发现位图一些主要的结构能够进行整理,得出下面图表:
进行图片缩放的时候会进行一些处理(最临近差值法):
详细的代码例如以下:
#include <stdio.h> #include <string.h> #include <math.h> #include <windows.h> #include <stdlib.h> LONG IWidth; //原图像的宽 LONG IHeight; //原图像的高 LONG biBitCount; //每像素位数 LONG INewWidth; //新图像的宽 LONG INewHeight; //新图像的高 LONG ILineByte; //原图像数据每行的字节数 LONG INewLineByte; //新图像数据每行的字节数 float zoomnumber=1; //初始放大倍数赋值为1 unsigned char *pIBuf; //原图像像素指针 unsigned char *pINewBuf;//新图像像素指针 int ReadBmp(const char* bmpName)//以二进制方式读入指定的图像文件 { FILE *fp=fopen(bmpName,"rb"); if(fp==0) { printf("打开文件失败 "); return 0; } fseek(fp,sizeof(BITMAPFILEHEADER),0);//跳过位图文件头 BITMAPINFOHEADER head;//定义位图信息头结构体变量。存放在变量head中 fread(&head,sizeof(BITMAPINFOHEADER),1,fp);//获取图像的高、宽和每像素所占的位数,接收地址head。单个元素大小文件头大小。元素个数1个,输入流fp IWidth = head.biWidth; IHeight = head.biHeight; biBitCount = head.biBitCount; ILineByte = (IWidth *biBitCount/8+3)/4*4;//计算原图像每行字节数,/4*4以保证是4的倍数 pIBuf = new unsigned char [ILineByte *IHeight];//定义一个矩阵用以存放原图像像素信息。pIBuf指向首地址 fread(pIBuf,1,ILineByte *IHeight,fp);//获取源文件像素信息。接收地址pIBuf,单个元素大小1字节,元素个数每行字节数*行数,输入流fp return 1;//成功返回1 } int SaveBmp(const char* bmpName,unsigned char *imgBuf,int width,int height,int biBitCount)//图像存储 { if(!imgBuf)//假设没有像素数据传入,则函数返回 return 0; INewLineByte = (width * biBitCount/8+3)/4*4;//计算新图像每行字节数。/4*4以保证是4的倍数 FILE *fp = fopen(bmpName,"wb");//以二进制方式写文件 if(fp == 0) return 0; BITMAPFILEHEADER fileHead;//申请位图文件头结构变量,填写文件头信息 fileHead.bfType= 0x4d42;//bmp类型 fileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+ INewLineByte *height;//位图文件大小 fileHead.bfReserved1 = 0;//保留字 fileHead.bfReserved2 = 0;//保留字 fileHead.bfOffBits = 54;//文件头到实际的位图数据的偏移字节数。前三个部分字节数之和 fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);//将新图像数据写入文件,获取数据地址fileHead,单个元素大小文件头大小,元素个数1个,输入流fp BITMAPINFOHEADER head;//定义位图信息头结构变量,存放在变量head中 head.biBitCount = biBitCount;//24位 head.biClrImportant = 0;//位图显示过程中重要的颜色数,觉得全部的颜色都是重要的 head.biClrUsed = 0;//位图实际用到的颜色数为2的biBitCount次幂 head.biCompression = 0;//位图压缩类型 head.biHeight = height;//新图像高 head.biPlanes =1;//目标设备的级别 head.biSize = 40;//本结构体长度 head.biSizeImage = ILineByte *height;//实际的位图数据占用的字节数 head.biWidth = width;//新图像宽 head.biXPelsPerMeter = 0;//指定目标设备的水平分辨率 head.biYPelsPerMeter = 0;//指定目标设备的垂直分辨率 fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);//写入信息头 fwrite(imgBuf,height * INewLineByte,1,fp);//写入像素数据 fclose(fp);//关闭文件 return 1; } int Zoom(const char* readPath )//图像缩放 { char address[50]; ReadBmp(readPath);//读取图像 INewWidth = (int) ((IWidth * zoomnumber) +0.5);//新图像的宽度。此处加0.5是因为强制转换时不四舍五入,而是直接截去小数部分 INewHeight = (int) (IHeight * zoomnumber +0.5);//新图像的高带。此处加0.5是因为强制转换时不四舍五入,而是直接截去小数部分 ILineByte =(IWidth*biBitCount/8+3)/4*4;//原图像每行字节数 INewLineByte = (INewWidth * biBitCount/8+3)/4*4;//新图像每行字节数 pINewBuf = new unsigned char [INewLineByte * INewHeight];//定义一个矩阵用以存放新图像像素信息,pIBuf指向首地址 LONG i; //循环变量(像素在新图像中的坐标) LONG j; LONG k; //色彩选择,k=0时为蓝色,k=1时为绿色,k=2时为红色 LONG i0; //像素在原图像中的坐标 LONG j0; if(biBitCount == 24) { for(i = 0;i < INewHeight;i++) { for(j = 0; j < INewWidth;j++) for(k=0;k<3;k++) { i0 = (int)(i/zoomnumber+0.5); j0 = (int)(j/zoomnumber+0.5); if((j0 >= 0) && (j0 < IWidth) && (i0 >=0)&& (i0 <IHeight)) { *(pINewBuf+i*INewLineByte+j*3+k) = *(pIBuf+i0*ILineByte+j0*3+k);//最邻近插值 } else { *(pINewBuf+i*INewLineByte+j*3+k)=255; } } } } printf("输入bmp图像缩放后需保存的路径名称和后缀:"); gets(address); SaveBmp(address,pINewBuf,INewWidth,INewHeight,biBitCount);//调用SaveBmp函数保存图像 delete []pINewBuf;//清除指针 return 1; } void main() { char filepath[256]; printf("请输入bmp图片路径,名称和后缀:(如E:1.bmp)"); scanf("%s",filepath); ReadBmp(filepath);//调用ReadBmp函数 printf("请输入所要缩放的倍数(小于1为缩小,大于1为放大):"); scanf("%f",&zoomnumber);getchar(); Zoom(filepath); }
验证下面图片效果还能够。