矩阵论还真有用:图片缩放旋转

本文介绍了一种使用C语言实现的BMP图片旋转与缩放的方法。通过对BMP文件格式的理解,利用三角函数计算旋转后的像素坐标,并通过缩放因子调整图片尺寸。文章还涉及了内存操作和文件读写等技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>


#define SCREEN_W 800
#define SCREEN_H 480


//#pragma pack(1)


typedef struct{
    short  bfType;     //bfType(2字节),这里恒定等于&H4D42,ASCII字符'BM'
    unsigned int bfSize;     //文件大小,以4字节为单位
    short  bfReserve1; //备用
    short  bfReserve2; //备用
    unsigned int bfoffBits;  //数据区在文件中的位置偏移量
}__attribute__((packed))BITMAPFILEHEADER;   //文件头结构体,14字节


typedef struct{
    long bitSize;    //位图信息头大小 本结构体大小 40btye
    long biWidth;    //图象宽度,像素单位
    long biHeight;   //图象高度,像素单位
    short  biPlanes;   //位平面树=1
    short  biBitCount; //单位像素的位数,表示bmp图片的颜色位数,即24位图、32位图
    long biCompression;  //图片的压缩属性,bmp图片是不压缩的,等于0
    long biSizeImage;    //表示bmp图片数据区的大小,当上一个属性biCompression等于0时,这里的值可以省略不填
    long biXPlosPerMeter;//水平分辨率,可省略
    long biYPlosPerMeter;//垂直分辨率,可省略
    long biClrUsed;      //表示使用了多少个颜色索引表,一般biBitCount属性小于16才会用到,
                                  //等于0时表示有2^biBitCount个颜色索引表
    long biClrImportant; //表示有多少个重要的颜色,等于0时表示所有颜色都很重要
}BITMAPINFOHEADER;       //位图信息头,40字节


typedef struct tagRGBQUAD {
    unsigned char rgbBlue;     // 蓝色的亮度(值范围为0-255)
    unsigned char rgbGreen;    // 绿色的亮度(值范围为0-255)
    unsigned char rgbRed;      // 红色的亮度(值范围为0-255)
    unsigned char rgbReserved; // 保留,必须为0
} RGBQUAD;


typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER bmiHeader; // 位图信息头
    RGBQUAD bmiColors[1];       // 颜色表
} BITMAPINFO;


//#pragma pack()


struct pic_obj {
    int nxp,nyp;
    unsigned bmap[256];
    unsigned char *data;        
};

struct pic_obj pics[2] = {0};
//将图片读入内存
int init_pics(const char *file, int num)
{
    int i, j;
    int nread;
    FILE *fp;
    char buf[1024*4];
    BITMAPFILEHEADER header;
    BITMAPINFOHEADER info;
    
    fp = fopen(file, "rb");
    if(fp == NULL){
        printf("open pic failed!\n");
    }

    nread = fread(&header, 1, sizeof(BITMAPFILEHEADER), fp);
    if(nread != sizeof(BITMAPFILEHEADER)){
        printf("read header fail\n");
    }
    
    nread = fread(&info, 1, sizeof(BITMAPINFOHEADER), fp);
    if(nread != sizeof(BITMAPINFOHEADER)){
        printf("read info fail\n");
    }

    nread = fread(buf, 1, sizeof(RGBQUAD)*256, fp);    
    if(nread != sizeof(RGBQUAD)*256){
        printf("read pic map!\n");
    }

    pics[num].nxp = info.biWidth;
    pics[num].nyp = info.biHeight;

    unsigned int value;
    RGBQUAD *rgbmap = buf;

    pics[num].data = (unsigned char *)malloc(header.bfSize - header.bfoffBits);

    nread = fread(pics[num].data, 1, header.bfSize - header.bfoffBits, fp); 
    if(nread != header.bfSize - header.bfoffBits){
        printf("read pic data failed!\n");
    }

    fclose(fp);

    return 0;
}

//x = x*c - y*s
//y = x*s + y*c

unsigned char gbuf[10*1024*1024] = {0,};
float cbuf[2000]={0,};
float sbuf[2000]={0,};
float scbuf[2000]={0,};

int main(int argc,char *argv[])
{
    int i,j;    

    int ang = atoi(argv[1]);
    float scal = (float)atoi(argv[2])/100;
    init_pics("./in.bmp",0);
    
    float c = cos(ang*3.1415926/180);
    float s = sin(ang*3.1415926/180);
    int tmp = sizeof(sbuf)/sizeof(sbuf[0])/2;


    for(i=0;i<sizeof(cbuf)/sizeof(cbuf[0]);i++){
        cbuf[i] = (i-tmp)*c;
        sbuf[i] = (i-tmp)*s;
        scbuf[i] = (i-tmp)*scal;
    }    

    printf("%f,%f,%f\n",c,s,scal);
    printf("%f,%f,%f\n",cbuf[50],sbuf[50],scal);
    printf("%f,%f,%f\n",cbuf[100],sbuf[100],scal);
    
    int w = pics[0].nxp;
    int h = pics[0].nyp;
    
    char *dat = malloc(w*h);
    memset(dat,0,w*h);
    
    int w2 = w/2;
    int h2 = h/2;    
    
    int jj = -1*w;
    unsigned char *ptr[1000]={0,}; 
    for(i=0; i < h; i++){
        ptr[i] = &pics[0].data[i*w];
    }

    //c=0;
    //s=1;

    for(i=0; i < h; i++){
        jj += w;
        for(j=0; j < w; j++){
            int xx,yy,xc,yc;
            
            //xx = j - w/2;
            //yy = h/2 - i;
            //xc = xx*c - yy*s;
            //yc = xx*s + yy*c;
            //xc = xc*scal + w/2;
            //yc = h/2 + yc*scal;
            
            xx = j - w2;
            yy = h2 - i;
            xc = cbuf[xx+tmp] - sbuf[yy+tmp];
            yc = sbuf[xx+tmp] + cbuf[yy+tmp];
            xc = scbuf[xc+tmp] + w2;
            yc = h2 + scbuf[yc+tmp];


            if(xc >= 0 && xc < w && yc >= 0 && yc < h){
                //dat[(h-yc)*w+xc] = pics[0].data[i*w+j];
                //dat[jj+j] = pics[0].data[(h-yc)*w+xc];
                dat[jj+j] = ptr[h-yc-1][xc];
            }
            
        }
    }
    
    #if 0
    for(i=1; i < h-1; i++){
        for(j=1; j < w-1; j++){
            if(dat[i*w+j] == 0){
                //dat[i*800+j] = (dat[i*800+j+1]+dat[i*800+j-1]+
                //dat[(i+1)*800+j]+dat[(i-1)*800+j])/4;
                dat[i*w+j] = dat[(i+1)*w+j];
            }            
        }
    }
    #endif
    
    FILE *outfp = fopen("out.bmp","w+");
    FILE *infp = fopen("in.bmp","r+");
    
    fread(gbuf,sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256,1,infp);
    fwrite(gbuf,sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256,1,outfp);
    
    fwrite(dat,w*h,1,outfp);

    free(dat);
    fclose(infp);
    fclose(outfp);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值