zoukankan      html  css  js  c++  java
  • BMP的图像处理

    近期碰到了一个问题将图片缩放:

    进行了整理发现位图一些主要的结构能够进行整理,得出下面图表:


    进行图片缩放的时候会进行一些处理(最临近差值法):

    详细的代码例如以下:

    #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);  	
    }

    验证下面图片效果还能够。



  • 相关阅读:
    没有完成的题目
    哈尔滨工程大学 ACM online contest 1008 how many
    POJ 2976 分数规划
    长沙理工 ACM 数位 DP 1488
    POJ 2663
    USETC 1821 AC 自动机
    长沙理工 ACM 分数规划 1494
    正则表达式基础知识(转)
    上传头像代码
    datalist 分页(转)
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7137718.html
Copyright © 2011-2022 走看看