C语言 BMP图片的旋转与缩放

目录

一、bmp文件头、文件信息头、位图实际数据的数据结构定义 

二、源BMP文件信息的读取

三、实际位图数据的旋转、缩放操作

四、生成转换过后的新位图文件

#include <stdlib.h>
 
#ifndef PHOTODEAL_H
#define PHOTODEAL_H
 
#pragma pack(1)
typedef struct tagBmpFileHeader{
    unsigned short bfType;
    unsigned long bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned long bfOffBits;
}BMPFILEHEADER;
typedef struct tagBmpInfoHeader{
    unsigned long biSize;
    long biWidth;
    long biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    long biXPelsPerMeter;
    long biYPelsPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
}BMPINFOHEADER;
typedef struct tagPalEn{
    unsigned char rgbRed;
    unsigned char rgbGreen;
    unsigned char rgbBlue;
    unsigned char rgbFlags;
}PALEN;
typedef struct tagPalette{
    unsigned short palVersion;
    unsigned short palNumEntries;
    PALEN palPalEN[1];
}PALETTE;
 
#pragma pack()
 
 
void OnLoad(char* path, BMPFILEHEADER* srcBmpFileHeader, BMPINFOHEADER* srcBmpInfoHeader, unsigned char** srcBmpData);
void WriteData(char* path, BMPFILEHEADER* desBmpFileHeader, BMPINFOHEADER* desBmpInfoHeader, unsigned char* desBmpData);
void RotateBmp(BMPFILEHEADER* srcBmpFileHeader, BMPINFOHEADER* srcBmpInfoHeader, BMPFILEHEADER* desBmpFileHeader, BMPINFOHEADER* desBmpInfoHeader, unsigned char** srcBmpData, /*double dAngle,*/ unsigned char* desBmpData);
void ZoomBmp(BMPFILEHEADER* srcBmpFileHeader, BMPINFOHEADER* srcBmpInfoHeader, BMPFILEHEADER* desBmpFileHeader, BMPINFOHEADER* desBmpInfoHeader,
    unsigned char* srcBmpData, unsigned char** desBmpData /*, int zmHeight, int zmWidth, , double dxRate, double dyRate*/);
 
void start();
//void suofang();
 
 
 
 
 
#endif
 
#define _CRT_SECURE_NO_WARNINGS
#include "PHOTODEAL.h"
#include <stdio.h>
//#include <stdlib.h>
#include <string.h>
#include <math.h>
 
BMPFILEHEADER srcBmpFileHeader, desBmpFileHeader;
BMPINFOHEADER srcBmpInfoHeader, desBmpInfoHeader;
unsigned char* srcBmpData = NULL;
unsigned char* desBmpData = NULL;
 
void OnLoad(char* path, BMPFILEHEADER* srcBmpFileHeader, BMPINFOHEADER* srcBmpInfoHeader, unsigned char** srcBmpData){
    FILE* pFile;
    unsigned char* tempData;//临时存储转换前的源图数据
 
    pFile = fopen(path, "rb");
    if (pFile == NULL){
        printf("Cann't open the file %s", path);
    }
 
    //读取文件头
    fread(srcBmpFileHeader, sizeof(BMPFILEHEADER), 1, pFile);
    printf("\n==============================================================\n");
    printf("文件类型标识符:0x%x\n", srcBmpFileHeader->bfType);
    printf("文件大小:%d_%d(kb)\n", srcBmpFileHeader->bfSize, srcBmpFileHeader->bfSize / 1024);
    printf("保留字1:%d\n保留字2:%d\n", srcBmpFileHeader->bfReserved1, srcBmpFileHeader->bfReserved2);
    printf("文件头开始到位图实际数据开始位的偏移字节:%d\n", srcBmpFileHeader->bfOffBits);
    //读取文件信息头
    fread(srcBmpInfoHeader, sizeof(BMPINFOHEADER), 1, pFile);
    printf("\n==============================================================\n");
    printf("文件信息头大小:%d\n", srcBmpInfoHeader->biSize);
    printf("位图宽度,像素:%d\n", srcBmpInfoHeader->biWidth);
    printf("位图高度,像素:%d\n", srcBmpInfoHeader->biHeight);
    printf("位图实际数据大小:%d_%d(kb)\n", srcBmpInfoHeader->biSizeImage, srcBmpInfoHeader->biSizeImage / 1024);
    printf("位图颜色使用的调色板数量:%d\n", srcBmpInfoHeader->biPlanes);
    printf("位图颜色使用的位(bit): %d\n", srcBmpInfoHeader->biBitCount);
    printf("位图实际使用的颜色数:%d\n", srcBmpInfoHeader->biClrUsed);
    printf("位图使用的重要颜色数:%d\n", srcBmpInfoHeader->biClrImportant);
    printf("位图是否压缩:%d\n", srcBmpInfoHeader->biCompression);
 
    //读取位图实际数据
    printf("\n==============================================================\n");
 
    tempData = (unsigned char*)malloc(sizeof(unsigned char)*srcBmpInfoHeader->biSizeImage);
    memset(tempData, 0, srcBmpInfoHeader->biSizeImage);
 
    if (srcBmpInfoHeader->biBitCount == 24){
        printf("该图为真彩色图 !\n");
        fread(tempData, sizeof(unsigned char), sizeof(unsigned char)*srcBmpInfoHeader->biSizeImage, pFile);//临时存储读取的转换前源图数据
 
        fclose(pFile);
 
        //将位图数据转换为每个像素4字节形式,计算转换后的图像大小
        int sizeofbuff = srcBmpInfoHeader->biWidth * srcBmpInfoHeader->biHeight * 4;
        //计算位图每行填充的字节数
        int externWidth = srcBmpInfoHeader->biWidth * 3;
        (externWidth % 4 != 0) ? (externWidth = 4 - externWidth % 4) : (externWidth = 0);
        //为转换后的位图数据分配空间
        *srcBmpData = (unsigned char*)malloc(sizeof(unsigned char) * sizeofbuff);
        //复制转换后的数据到srcBmpData
        int k = 0;
        for (/*int i = srcBmpInfoHeader->biHeight - 1; i >= 0; i--*/int i = 0; i < srcBmpInfoHeader->biHeight; i++){
            for (int j = 0; j < srcBmpInfoHeader->biWidth * 3; j += 3){
                (*srcBmpData)[k] = tempData[i * (srcBmpInfoHeader->biWidth * 3 + externWidth) + j + 0];
                (*srcBmpData)[k + 1] = tempData[i * (srcBmpInfoHeader->biWidth * 3 + externWidth) + j + 1];
                (*srcBmpData)[k + 2] = tempData[i * (srcBmpInfoHeader->biWidth * 3 + externWidth) + j + 2];
                (*srcBmpData)[k + 3] = 255;//第四位填充为255
                k += 4;
            }
        }
        
        free(tempData);
    }
 
 
 
}
void WriteData(char* path, BMPFILEHEADER* desBmpFileHeader, BMPINFOHEADER* desBmpInfoHeader, unsigned char* desBmpData){
    FILE* pFile;
 
    /*char* tempName;
    char* newName;
    memcpy(tempName, path, strlen(path) - 4);*/
    pFile = fopen(path, "wb");
 
    //写入文件头
    fwrite(desBmpFileHeader, sizeof(BMPFILEHEADER), 1, pFile);
    //写入文件信息头
    fwrite(desBmpInfoHeader, sizeof(BMPINFOHEADER), 1, pFile);
    //写入位图实际数据
    unsigned int outHeight = desBmpInfoHeader->biHeight;
    unsigned int outWidth = desBmpInfoHeader->biWidth;
 
    //指向旋转的图像数据的最后一行
    /*unsigned char** pListData = NULL;
    pListData =  &desBmpData + ((unsigned long)outHeight - 1) * outWidth * 4;
    不需要这段代码*/
 
    //计算需要填充的字节数
    unsigned char byByteAlign;
    if (outWidth % 4 != 0)
        byByteAlign = 4 - ((outWidth * 3) % 4);
    else
        byByteAlign = 0;
    unsigned char byZeroData = 0;
    for (unsigned int i = 0; i < outHeight; i++){
        for (unsigned int j = 0; j < outWidth; j++){
            fwrite(desBmpData, sizeof(unsigned char), 3, pFile);//写入位图实际数据
            desBmpData += 4;//指向下一个像素
        }
        for (int k = 0; k < byByteAlign; k++){
            fwrite(&byZeroData, sizeof(unsigned char), 1, pFile);
        }
    }
    //free(&pListData);
    fclose(pFile);
    printf("\n文件转换保存成功 !\n");
 
}
void RotateBmp(BMPFILEHEADER* srcBmpFileHeader, BMPINFOHEADER* srcBmpInfoHeader, BMPFILEHEADER* desBmpFileHeader, BMPINFOHEADER* desBmpInfoHeader,
    unsigned char* srcBmpData, /*double dAngle,*/ unsigned char** desBmpData){
    double dAngle;
    printf("\n请输入旋转角度:\n");
    scanf("%lf", &dAngle);
 
    //角度转弧度,计算正弦、余弦
    double PI = 3.141592653;
    double dRadian = dAngle * PI / 180.0;
    double dSin = sin(dRadian);
    double dCos = cos(dRadian);
 
    //计算目标图像的高度、宽度
    *desBmpFileHeader = *srcBmpFileHeader;
    *desBmpInfoHeader = *srcBmpInfoHeader;
    desBmpInfoHeader->biHeight = (int)((abs)(srcBmpInfoHeader->biHeight * dCos) + (abs)(srcBmpInfoHeader->biWidth * dSin) + 1);
    desBmpInfoHeader->biWidth = (int)((abs)(srcBmpInfoHeader->biHeight * dSin) + (abs)(srcBmpInfoHeader->biWidth * dCos) + 1);
    printf("desWidth = %d - desHeight = %d\n", desBmpInfoHeader->biWidth, desBmpInfoHeader->biHeight);
    //计算每行字节数及填充字节数
    //unsigned int desLineBytes = desBmpInfoHeader->biWidth * desBmpInfoHeader->biBitCount / 8; 此方式计算结果小于实际需求
    unsigned int desLineBytes = desBmpInfoHeader->biWidth * 4;
    printf("\n目标每行字节数:%d\n", desLineBytes);
    int mod = desLineBytes % 4;
    if (mod != 0)
        desLineBytes += 4 - mod;
 
    //为目标图像数据分配空间
    desBmpInfoHeader->biSizeImage = desBmpInfoHeader->biHeight * desLineBytes;
    printf("\n目标图像数据大小:%d\n", desBmpInfoHeader->biSizeImage);
    *desBmpData = (unsigned char*)malloc(sizeof(unsigned char) * desBmpInfoHeader->biSizeImage);
 
    double dX = -0.5 * desBmpInfoHeader->biWidth * dCos - 0.5 * desBmpInfoHeader->biHeight * dSin + 0.5 * srcBmpInfoHeader->biWidth;
    double dY = 0.5 * desBmpInfoHeader->biWidth * dSin - 0.5 * desBmpInfoHeader->biHeight * dCos + 0.5 * srcBmpInfoHeader->biWidth;
 
    int x = 0;
    int y = 0;
    for (int h = 0; h < desBmpInfoHeader->biHeight; h++){
        for (int w = 0; w < desBmpInfoHeader->biWidth; w++){
            x = (int)(w * dCos + h * dSin + dX + 0.5);//源图像像素点-横坐标
            y = (int)(-w *dSin + h *dCos + dY + 0.5);//源图像像素点-纵坐标
            if (x == srcBmpInfoHeader->biWidth){
                x--;
            }
            if (y == srcBmpInfoHeader->biHeight){
                y--;
            }
            if (x >= 0 && x < srcBmpInfoHeader->biWidth && y >= 0 && y < srcBmpInfoHeader->biHeight){
                memcpy((*desBmpData) + h*desBmpInfoHeader->biWidth * 4 + w * 4, srcBmpData + y*srcBmpInfoHeader->biWidth * 4 + x * 4, 4);
            }
        }
    }
}
void ZoomBmp(BMPFILEHEADER* srcBmpFileHeader, BMPINFOHEADER* srcBmpInfoHeader, BMPFILEHEADER* desBmpFileHeader, BMPINFOHEADER* desBmpInfoHeader,
    unsigned char* srcBmpData, unsigned char** desBmpData /*, int zmHeight, int zmWidth, , double dxRate, double dyRate*/){
    double dxRate, dyRate;
    printf("\n请输入缩放的比例:横轴纵轴\n");
    scanf("%lf %lf", &dxRate, &dyRate); getchar();
    计算压缩比
    //double dxRate = 0.0, dyRate = 0.0;
 
    //复制文件头、文件信息头相关信息
    *desBmpFileHeader = *srcBmpFileHeader;
    *desBmpInfoHeader = *srcBmpInfoHeader;
    //注意要修改 发生了变化的 文件头、文件信息头的相关信息
    //计算压缩后的图像宽度、高度
    desBmpInfoHeader->biWidth = srcBmpInfoHeader->biWidth * dxRate;
    desBmpInfoHeader->biHeight = srcBmpInfoHeader->biHeight * dyRate;
    //desBmpInfoHeader->biCompression = 0;
    
    //计算缩放后的图像数据字节数,获取缩放后的图像大小
    
    unsigned long dwSize = desBmpInfoHeader->biHeight * desBmpInfoHeader->biWidth * 4;//缩放后的图像大小
    *desBmpData = (unsigned char*)malloc(sizeof(unsigned char) * dwSize);
    memset(*desBmpData, 255, dwSize);
    unsigned char* tempBmpData = *desBmpData;
    unsigned char* pSrcData = srcBmpData;
 
    int nx = 0, ny = 0;//源位图像素点的纵横坐标
 
    //将源位图数据按比例缩放后复制到新位图数据中去
 
    for (int i = 0; i < desBmpInfoHeader->biHeight; i++){
        ny = (int)(i / dyRate + 0.5);
        if (ny >= srcBmpInfoHeader->biHeight){
            ny--;
        }
        for (int j = 0; j < desBmpInfoHeader->biWidth; j++){
            nx = (int)(j / dxRate + 0.5);
            if (nx >= srcBmpInfoHeader->biWidth){
                nx--;
            }
            pSrcData = srcBmpData + (srcBmpInfoHeader->biWidth) * ny * 4 + nx * 4;
            memcpy(tempBmpData, pSrcData, 4);
            tempBmpData += 4;
        }
    }
    
 
}
 
void(*bbb[])(BMPFILEHEADER* srcBmpFileHeader, BMPINFOHEADER* srcBmpInfoHeader, BMPFILEHEADER* desBmpFileHeader, BMPINFOHEADER* desBmpInfoHeader,
    unsigned char * srcBmpData, unsigned char** desBmpData) = { RotateBmp, ZoomBmp };//函数指针
 
void start(){
    char path[15];
    printf("请输入要旋转的图片名称:\n");
    scanf("%s", path); getchar();
    
    OnLoad(path, &srcBmpFileHeader, &srcBmpInfoHeader, &srcBmpData);
    printf("\n选择要处理的类型:\n");
    printf("0-旋转图片\n");
    printf("1-缩放图片\n");
    int choice;
    printf("请选择:\n");
    scanf("%d", &choice); getchar();
    bbb[choice](&srcBmpFileHeader, &srcBmpInfoHeader, &desBmpFileHeader, &desBmpInfoHeader, srcBmpData, &desBmpData);
    char savePath[15];
    printf("\n请输入要保存的名称:\n");
    scanf("%s", savePath); getchar();
    WriteData(savePath, &desBmpFileHeader, &desBmpInfoHeader, desBmpData);
 
}

// writeBmpDlg.cpp : implementation file
//

#include "stdafx.h"
#include "writeBmp.h"
#include "writeBmpDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CWriteBmpDlg dialog

CWriteBmpDlg::CWriteBmpDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CWriteBmpDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CWriteBmpDlg)
	m_d = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CWriteBmpDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CWriteBmpDlg)
	DDX_Text(pDX, IDC_EDIT1, m_d);
	DDV_MinMaxInt(pDX, m_d, -360, 360);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CWriteBmpDlg, CDialog)
	//{{AFX_MSG_MAP(CWriteBmpDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
	ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
	ON_BN_CLICKED(IDC_BUTTON4, OnButton4)
	ON_BN_CLICKED(IDC_BUTTON5, OnButton5)
	ON_BN_CLICKED(IDC_BUTTON6, OnButton6)
	ON_BN_CLICKED(IDC_BUTTON7, OnButton7)
	ON_BN_CLICKED(IDC_BUTTON8, OnButton8)
	ON_BN_CLICKED(IDC_BUTTON9, OnButton9)
	ON_BN_CLICKED(IDC_BUTTON10, OnButton10)
	ON_BN_CLICKED(IDC_BUTTON11, OnButton11)
	ON_BN_CLICKED(IDC_BUTTON12, OnButton12)
	ON_BN_CLICKED(IDC_BUTTON13, OnButton13)
	ON_BN_CLICKED(IDC_BUTTON14, OnButton14)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CWriteBmpDlg message handlers
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
BOOL CWriteBmpDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
/*
	FILE *fp;
	fp = fopen("000.bmp","rb+");
	fread(&bf,sizeof(bf),1,fp);//借用已有的bmp头文件格式
    fread(&bi,sizeof(bi),1,fp);//可以详细了解这个两个结构
	fclose(fp);
//*/
	m_d = 30;
	UpdateData(FALSE);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CWriteBmpDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CWriteBmpDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CWriteBmpDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

unsigned char buf[640*480*3];//bmp数据buf
unsigned char gray;
int hight,width;

unsigned char bmpHeader[54]=
{0x42,0x4d,0x38,0x10,0x0e,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
 0x00,0x00,0x80,0x02,0x00,0x00,0xe0,0x01,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
 0x00,0x00,0x02,0x10,0x0e,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00
};


void CWriteBmpDlg::OnButton1() 
{
	// TODO: Add your control notification handler code here
	FILE *fp;
    //构造1x1竖线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(width%2 == 0)
			{
				gray = 0x00;//白
			   
			}
			else
			{
			    gray = 0xff;//黑
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("1x1_竖线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::showbmp()
{
    CWindowDC dc(this);

	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    BYTE	b = buf[(hight*640+width)*3 + 0];
			BYTE	g = buf[(hight*640+width)*3 + 1];
			BYTE	r = buf[(hight*640+width)*3 + 2];
			dc.SetPixel(width+50,hight+150,RGB(r,g,b));
		}
	}


}

void CWriteBmpDlg::OnButton2() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造4x4竖线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(width%4 == 0 || width%4 == 1)
			{
				gray = 0x00;//白
			   
			}
			else
			{
			    gray = 0xff;//黑
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("2x2_竖线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton3() 
{
	// TODO: Add your control notification handler code here
			FILE *fp;
    //构造4x4竖线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(width%8 == 0 || width%8 == 1||width%8 == 2 || width%8 == 3)
			{
				gray = 0x00;//白
			   
			}
			else
			{
			    gray = 0xff;//黑
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("4x4_竖线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton4() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造1x1横线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(hight%2 == 0)
			{
				gray = 0x00;//白
			   
			}
			else
			{
			    gray = 0xff;//黑
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("1x1_横线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton5() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造2x2横线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(hight%4 == 0 || hight%4 == 1)
			{
				gray = 0x00;//白
			   
			}
			else
			{
			    gray = 0xff;//黑
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("2x2_横线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton6() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造4x4横线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(hight%8 == 0 || hight%8 == 1||hight%8 == 2 || hight%8 == 3)
			{
				gray = 0x00;//白
			   
			}
			else
			{
			    gray = 0xff;//黑
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("4x4_横线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton7() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造黑白四分屏
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(width<320 )
			{
				if(hight<240)
				{
					gray = 0x00;//白
				}
				else
				{
				    gray = 0xff;//白
				}
			}
			else
			{
			   	if(hight<240)
				{
					gray = 0xff;//白
				}
				else
				{
				    gray = 0x00;//白
				}
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("黑白四分屏.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton8() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造灰度四分屏
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(width<320 )
			{
				if(hight<240)
				{
					gray = 0xD0;//
				}
				else
				{
				    gray = 0xA0;//
				}
			}
			else
			{
			   	if(hight<240)
				{
					gray = 0x80;//
				}
				else
				{
				    gray = 0x40;//
				}
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("灰度四分屏.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton9() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造彩色四分屏
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(width<320 )
			{
				if(hight<240)
				{
					buf[(hight*640+width)*3 + 0]= 0xff;//b
					buf[(hight*640+width)*3 + 1]= 0;//g
					buf[(hight*640+width)*3 + 2]= 0;//r
				}
				else
				{
				    buf[(hight*640+width)*3 + 0]= 0x00;//b
					buf[(hight*640+width)*3 + 1]= 0xff;//g
					buf[(hight*640+width)*3 + 2]= 0;//r
				}
			}
			else
			{
			   	if(hight<240)
				{
					buf[(hight*640+width)*3 + 0]= 0;//b
					buf[(hight*640+width)*3 + 1]= 0;//g
					buf[(hight*640+width)*3 + 2]= 0xff;//r
				}
				else
				{
				    buf[(hight*640+width)*3 + 0]= 0;//b
					buf[(hight*640+width)*3 + 1]= 0xff;//g
					buf[(hight*640+width)*3 + 2]= 0xff;//r
				}
			} 
		
		}
	}

	//保存bmp文件
   fp = fopen("彩色四分屏.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

#include <math.h>
int round(float f)
{
if ((int)f+0.5>f)
return (int)f;
else
return (int)f + 1;
}
#define CV_PI 3.1415926
void CWriteBmpDlg::OnButton10() 
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);
///*	
CString pathName,tmp;
	TCHAR szFilters[]= _T("MyType Files (*.bmp)|*.my|All Files (*.*)|*.*||");
	CFileDialog fileDlg(TRUE, _T("bmp"), _T("*.bmp"),
      OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);
     if(fileDlg.DoModal() == IDOK)
	 {
       pathName = fileDlg.GetPathName();
	 }
	 else
	 {
		 MessageBox("重新选择图片");
		 return;
	 }
//*/
	FILE *fp = fopen(pathName, "rb");
	if (fp == 0)
	{
		printf("文件打开失败\n");
		return ;
	}
 
	BITMAPFILEHEADER fileHead;
	BITMAPINFOHEADER infoHead;
	fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);
 
	int width = infoHead.biWidth;
	int height = infoHead.biHeight;
	int biCount = infoHead.biBitCount;
	int lineByte = (width*biCount / 8 + 3) / 4 * 4;
 
//	RGBQUAD *pColorTable;
 
//	pColorTable = new RGBQUAD[256];
//	fread(pColorTable, sizeof(RGBQUAD), 256, fp);
 
	unsigned char *pBmpBufSrc,*pBmpBufDst;
	pBmpBufSrc = new unsigned char[lineByte*height];
	fread(pBmpBufSrc, lineByte*height, 1, fp);//640*480*3
	fclose(fp);
 
   //显示原始图像到窗口
    //
	CWindowDC dc(this);

	for(int i=0;i<height;i++)
	{
	    for(int k=0;k<width;k++)
		{
		    BYTE	b = pBmpBufSrc[(i*width+k)*3 + 0];
			BYTE	g = pBmpBufSrc[(i*width+k)*3 + 1];
			BYTE	r = pBmpBufSrc[(i*width+k)*3 + 2];
			dc.SetPixel(k+50,height-i+150,RGB(r,g,b));
		}
	}//*/
	///

	Sleep(1000);
	double angle=m_d;//旋转度数

 
	double sita = angle*CV_PI / 180;
	double a = (width - 1) / 2;//中心值
	double b = (height - 1) / 2;
    
	double x1 = -a*cos(sita) - b*sin(sita);//第2象限顶点
	double y1 = -a*sin(sita) + b*cos(sita);
 
	double x2 = a*cos(sita) - b*sin(sita);//第1象限
	double y2 = a*sin(sita) + b*cos(sita);
 
	double x3 = a*cos(sita) + b*sin(sita);//第4象限
	double y3 = a*sin(sita) - b*cos(sita);
 
	double x4 = -a*cos(sita) + b*sin(sita);//第3象限
	double y4 = -a*sin(sita) - b*cos(sita);
 
	int w1 = round(max(abs(x1 - x3), abs(x2 - x4)));//旋转后的宽度,高度
	int h1 = round(max(abs(y1 - y3), abs(y2 - y4)));//取最大值
 
	double c = (w1 - 1) / 2;//旋转后的中心
	double d = (h1 - 1) / 2;
 
	double f1 = -c*cos(sita) + d*sin(sita) + a;
	double f2 = -c*sin(sita) - d*cos(sita) + b;
 
	int lineByte1 = (w1*biCount / 8 + 3) / 4 * 4;
//	int rgbData;
	pBmpBufDst = new unsigned char[lineByte1*h1];
 
	初始化目标图像buf
	for (  i = 0; i < h1; ++i)
	{
		for (int j = 0; j < w1; ++j)
		{
		//	unsigned char *p;
		//	p = (unsigned char *)(pBmpBufDst + i*lineByte1 + j);
		//	(*p++) = 255;(*p++) = 255;(*p++) = 255;
			//rgb模式
			 *(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3+0) = 0xAA;
			 *(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3+1) = 0xAA;
			 *(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3+2) = 0xAA;
		}
	}
 
    unsigned char *p1, *p2;
	for ( i = 0; i < h1; ++i)
	{
		for (int j = 0; j < w1; ++j)
		{
			int x = round(j*cos(sita) - i*sin(sita) + f1); //(i,j)为旋转后的坐标(0,0),计算出在原图的坐标(x,y)
			int y = round(j*sin(sita) + i*cos(sita) + f2);
			if (x>0 && x<width && y>0 && y < height)       //如果(x,y)落入原图640*480区间,赋颜色值
			{
				
				p1 = (unsigned char *)(pBmpBufDst + i*lineByte1 + j*3); // 新图像
				p2 = (unsigned char *)(pBmpBufSrc + y*lineByte + x*3);  // 原图像
			//	(*p1) = (*p2);
                
				memcpy(p1,p2,3);
			}
			
		}
		continue;
	}
 
	tmp.Format("-旋转%d度.bmp",m_d);
	pathName += tmp;
	char *DstName = "rotate.bmp";
	FILE *fpo = fopen(pathName, "wb");
	if (fpo == 0)
		return ;
	int colorTableSize = 0;
	if (biCount == 8)
		colorTableSize = 1024;
	BITMAPFILEHEADER dstFileHead;
	dstFileHead.bfOffBits = 14 + 40 + colorTableSize;
	dstFileHead.bfReserved1 = 0;
	dstFileHead.bfReserved2 = 0;
	dstFileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTableSize + lineByte1*h1;
	dstFileHead.bfType = 0x4D42;
	fwrite(&dstFileHead, sizeof(dstFileHead), 1, fpo);
	
	BITMAPINFOHEADER dstInfoHead;
	dstInfoHead.biBitCount = biCount;
	dstInfoHead.biClrImportant = 0;
	dstInfoHead.biClrUsed = 0;
	dstInfoHead.biCompression = 0;
	dstInfoHead.biHeight = h1;
	dstInfoHead.biPlanes = 1;
	dstInfoHead.biSize = 40;
	dstInfoHead.biSizeImage = lineByte1*h1;
	dstInfoHead.biWidth = w1;
	dstInfoHead.biXPelsPerMeter = 0;
	dstInfoHead.biYPelsPerMeter = 0;
	fwrite(&dstInfoHead, sizeof(BITMAPINFOHEADER), 1, fpo);
	
//	fwrite(pColorTable, sizeof(RGBQUAD), 256, fpo);
	fwrite(pBmpBufDst, lineByte1*h1, 1, fpo);
	fclose(fpo);


	//显示原始图像到窗口
    //
//	CWindowDC dc(this);

	for(hight=0;hight<h1;hight++)
	{
	    for(width=0;width<w1;width++)
		{
		    BYTE	b = pBmpBufDst[lineByte1*hight + 3*width + 0];
			BYTE	g = pBmpBufDst[lineByte1*hight + 3*width + 1];
			BYTE	r = pBmpBufDst[lineByte1*hight + 3*width + 2];
			dc.SetPixel(width+50,h1-hight+150,RGB(r,g,b));
		}

	}
	///
}

void CWriteBmpDlg::OnButton11() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造1x1横线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(hight == 240 || width==320)
			{
				gray = 0x00;//黑
			   
			}
			else
			{
			    gray = 0xff;//白
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("十字线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton12() 
{
	// TODO: Add your control notification handler code here
		FILE *fp;
    //构造1x1横线数据
	for(hight=0;hight<480;hight++)
	{
	    for(width=0;width<640;width++)
		{
		    if(width==320)
			{
				gray = 0x00;//黑
			   
			}
			else
			{
			    gray = 0xff;//白
			} 
			buf[(hight*640+width)*3 + 0]= gray;//b
			buf[(hight*640+width)*3 + 1]= gray;//g
			buf[(hight*640+width)*3 + 2]= gray;//r
		}
	}

	//保存bmp文件
   fp = fopen("单竖线.bmp","wb+");

//	fwrite(&bf,sizeof(bf),1,fp);
 //   fwrite(&bi,sizeof(bi),1,fp);
    fwrite(bmpHeader,54,1,fp);//直接写bmp头
	fwrite(buf,640*480*3,1,fp);
	fclose(fp);

	//显示到窗口
    showbmp();
}

void CWriteBmpDlg::OnButton13() 
{
	// TODO: Add your control notification handler code here
		UpdateData(TRUE);

	int width = 640;//infoHead.biWidth;
	int height = 480;//infoHead.biHeight;
	int biCount = 24;//infoHead.biBitCount;
//	int lineByte = (width*biCount / 8 + 3) / 4 * 4;
 
//	RGBQUAD *pColorTable;
 
//	pColorTable = new RGBQUAD[256];
//	fread(pColorTable, sizeof(RGBQUAD), 256, fp);
 
	unsigned char *pBmpBufSrc,*pBmpBufDst;
//	pBmpBufSrc = new unsigned char[lineByte*height];
//	fread(pBmpBufSrc, lineByte*height, 1, fp);//640*480*3
//	fclose(fp);
 
	double angle=m_d;//旋转度数

 
	double sita = angle*CV_PI / 180;
	double a = (width - 1) / 2;//中心值
	double b = (height - 1) / 2;
    
	double x1 = -a*cos(sita) - b*sin(sita);//第2象限顶点
	double y1 = -a*sin(sita) + b*cos(sita);
 
	double x2 = a*cos(sita) - b*sin(sita);//第1象限
	double y2 = a*sin(sita) + b*cos(sita);
 
	double x3 = a*cos(sita) + b*sin(sita);//第4象限
	double y3 = a*sin(sita) - b*cos(sita);
 
	double x4 = -a*cos(sita) + b*sin(sita);//第3象限
	double y4 = -a*sin(sita) - b*cos(sita);
 
	int w1 = round(max(abs(x1 - x3), abs(x2 - x4)));//旋转后的宽度,高度
	int h1 = round(max(abs(y1 - y3), abs(y2 - y4)));//取最大值
    //(791,732)
	double c = (w1 - 1) / 2;//旋转后的中心
	double d = (h1 - 1) / 2;//(395,365)
 
	double f1 = -c*cos(sita) + d*sin(sita) + a;//159.4
	double f2 = -c*sin(sita) - d*cos(sita) + b;//-274.6
 
	int lineByte1 = (w1*biCount / 8 + 3) / 4 * 4;
	pBmpBufDst = new unsigned char[lineByte1*h1];
 
	初始化目标图像buf
	for (int i = 0; i < h1; ++i)
	{
		for (int j = 0; j < w1; ++j)
		{
		//	unsigned char *p;
		//	p = (unsigned char *)(pBmpBufDst + i*lineByte1 + j);
		//	(*p++) = 255;(*p++) = 255;(*p++) = 255;
			//rgb模式
			 *(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3+0) = 0xAA;
			 *(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3+1) = 0xAA;
			 *(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3+2) = 0xAA;
		}
	}
 
 
	for ( i = 0; i < h1; ++i)
	{
		for (int j = 0; j < w1; ++j)
		{
			int x = round(j*cos(sita) - i*sin(sita) + f1); //(i,j)为旋转后的坐标(0,0),计算出在原图的坐标(x,y)
			int y = round(j*sin(sita) + i*cos(sita) + f2);//(0,0)-->(159,-274)
            int y2=0;
			if (x>0 && x<width && y>0 && y < height)       //如果(x,y)落入原图640*480区间,赋颜色值
			{//(551,0)-->(637,1)
				unsigned char *p1, *p2,R;
				p1 = (unsigned char *)(pBmpBufDst + i*lineByte1 + j*3); // 新图像
//				p2 = (unsigned char *)(pBmpBufSrc + y*lineByte + x*3);  // 原图像
			//	(*p1) = (*p2);
			//	memcpy(p1,p2,3);
				R= *(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3 + 2) ;
				if(x==320)
				{
					if(R==0xAA)
					{
						*(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3 + 0) = 0x00; 
						*(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3 + 1) = 0x00; 
						*(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3 + 2) = 0x00; 
					}

#if 1
					y2 = round(j*tan((90-m_d)*1.0/180*3.1415926));
					y2 = abs(y2)-312;
					if(y2<h1)
					{
						*(unsigned char *)(pBmpBufDst + y2*lineByte1 + j*3 + 0) = 0x00; 
						*(unsigned char *)(pBmpBufDst + y2*lineByte1 + j*3 + 1) = 0x00; 
						*(unsigned char *)(pBmpBufDst + y2*lineByte1 + j*3 + 2) = 0xFF; 
					}
#endif 
				}
				else
				{
					if(R==0xAA)
					{
						*(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3 + 0) = 0xf0; 
						*(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3 + 1) = 0xf0; 
						*(unsigned char *)(pBmpBufDst + i*lineByte1 + j*3 + 2) = 0xf0; 
					}
				}
			}
		}
		continue;
	}
    CString str;
	str.Format("自划线旋转%d度.bmp",m_d);
//	pathName += tmp;
//	char *DstName = "rotate.bmp";
	FILE *fpo = fopen(str, "wb");
	if (fpo == 0)
		return ;
	int colorTableSize = 0;
	if (biCount == 8)
		colorTableSize = 1024;
	BITMAPFILEHEADER dstFileHead;
	dstFileHead.bfOffBits = 14 + 40 + colorTableSize;
	dstFileHead.bfReserved1 = 0;
	dstFileHead.bfReserved2 = 0;
	dstFileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTableSize + lineByte1*h1;
	dstFileHead.bfType = 0x4D42;
	fwrite(&dstFileHead, sizeof(dstFileHead), 1, fpo);
	
	BITMAPINFOHEADER dstInfoHead;
	dstInfoHead.biBitCount = biCount;
	dstInfoHead.biClrImportant = 0;
	dstInfoHead.biClrUsed = 0;
	dstInfoHead.biCompression = 0;
	dstInfoHead.biHeight = h1;
	dstInfoHead.biPlanes = 1;
	dstInfoHead.biSize = 40;
	dstInfoHead.biSizeImage = lineByte1*h1;
	dstInfoHead.biWidth = w1;
	dstInfoHead.biXPelsPerMeter = 0;
	dstInfoHead.biYPelsPerMeter = 0;
	fwrite(&dstInfoHead, sizeof(BITMAPINFOHEADER), 1, fpo);
	
//	fwrite(pColorTable, sizeof(RGBQUAD), 256, fpo);
	fwrite(pBmpBufDst, lineByte1*h1, 1, fpo);
	fclose(fpo);


	//显示原始图像到窗口
    //
	CWindowDC dc(this);

	for(hight=0;hight<h1;hight++)
	{
	    for(width=0;width<w1;width++)
		{
		    BYTE	b = pBmpBufDst[lineByte1*hight + 3*width + 0];
			BYTE	g = pBmpBufDst[lineByte1*hight + 3*width + 1];
			BYTE	r = pBmpBufDst[lineByte1*hight + 3*width + 2];
			dc.SetPixel(width+50,h1-hight+150,RGB(r,g,b));
		}
	}
	///
}

float a0,a1,a2;
int x[50],y[50];
void deal()//采用克莱默法则求解方程
{
	int i,n=50,select=1;
	float temp,temp0,temp1,temp2;
	float sy=0,sx=0,sxx=0,syy=0,sxy=0,sxxy=0,sxxx=0,sxxxx=0;//定义相关变量
	for(i=0;i<n;i++)
	{
		sx+=x[i];//计算xi的和
		sy+=y[i];//计算yi的和
		sxx+=x[i]*x[i];//计算xi的平方的和
		sxxx+=pow(x[i],3);//计算xi的立方的和
		sxxxx+=pow(x[i],4);//计算xi的4次方的和
		sxy+=x[i]*y[i];//计算xi乘yi的的和
		sxxy+=x[i]*x[i]*y[i];//计算xi平方乘yi的和
	}
	temp=n*sxx-sx*sx;//方程的系数行列式
	temp0=sy*sxx-sx*sxy;
	temp1=n*sxy-sy*sx;
	a0=temp0/temp;
	a1=temp1/temp;
	if(select==1)
	{
		printf("经最小二乘法拟合得到的一元线性方程为:\n"); 
		printf("f(x)=%3.3fx+%3.3f\n",a1,a0); 
		//		system("pause");
		return;
	}
	temp=n*(sxx*sxxxx-sxxx*sxxx)-sx*(sx*sxxxx-sxx*sxxx)//方程的系数行列式
		+sxx*(sx*sxxx-sxx*sxx);
	temp0=sy*(sxx*sxxxx-sxxx*sxxx)-sxy*(sx*sxxxx-sxx*sxxx)
		+sxxy*(sx*sxxx-sxx*sxx);
	temp1=n*(sxy*sxxxx-sxxy*sxxx)-sx*(sy*sxxxx-sxx*sxxy)
		+sxx*(sy*sxxx-sxy*sxx);
	temp2=n*(sxx*sxxy-sxy*sxxx)-sx*(sx*sxxy-sy*sxxx)
		+sxx*(sx*sxy-sy*sxx);
	a0=temp0/temp;
	a1=temp1/temp;
	a2=temp2/temp;
	if(select==2)
	{
		printf("经最小二乘法拟合得到的二次近似方程为:\n"); 
		printf("f(x)=%3.3fx2+%3.3fx+%3.3f\n",a2,a1,a0); 
	//	system("pause");
	}
	
}
void CWriteBmpDlg::OnButton14() 
{
	// TODO: Add your control notification handler code here
	CString pathName,tmp;
	TCHAR szFilters[]= _T("MyType Files (*.bmp)|*.my|All Files (*.*)|*.*||");
	CFileDialog fileDlg(TRUE, _T("bmp"), _T("*.bmp"),
      OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);
     if(fileDlg.DoModal() == IDOK)
	 {
       pathName = fileDlg.GetPathName();
	 }
	 else
	 {
		 MessageBox("重新选择图片");
		 return;
	 }
	 CPoint blackPoint[1000*100];
	 FILE *fp = fopen(pathName, "rb");
	if (fp == 0)
	{
		printf("文件打开失败\n");
		return ;
	}
 
	BITMAPFILEHEADER fileHead;
	BITMAPINFOHEADER infoHead;
	fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);
 
	int width = infoHead.biWidth;
	int height = infoHead.biHeight;
	int biCount = infoHead.biBitCount;
	int lineByte = (width*biCount / 8 + 3) / 4 * 4;
 
//	RGBQUAD *pColorTable;
 
//	pColorTable = new RGBQUAD[256];
//	fread(pColorTable, sizeof(RGBQUAD), 256, fp);
 
	unsigned char *pBmpBufSrc,*pBmpBufDst;
	pBmpBufSrc = new unsigned char[lineByte*height];
	fread(pBmpBufSrc, lineByte*height, 1, fp);//640*480*3
	fclose(fp);
    int pointCnt=0,flag=0;;
	for(int i=0;i<height;i++)
	{
		flag=0;
	    for(int j=0;j<width;j++)
		{
		     BYTE	b = pBmpBufSrc[(i*width+j)*3 + 0];
			 BYTE	g = pBmpBufSrc[(i*width+j)*3 + 1];
			 BYTE	r = pBmpBufSrc[(i*width+j)*3 + 2];
			 b=b+g+r;
			 if(b==0  &&  flag==0)
			 {
			//	 if(i==(height/2+50)  || i==(height/2-50))
				 {
					 flag=1;
					 blackPoint[pointCnt].x=j;
					 blackPoint[pointCnt++].y=i;
				 }

			 }
		}
	}
	
    float pp[4]={0};
	int num1,num2;
	num1=num2=0;
/*	for(int k=0;k<(pointCnt/2*2);k++)
	{
	     if(k<pointCnt/2)
		 {
		     pp[0] += blackPoint[k].x*1.0;
		     pp[1] += blackPoint[k].y*1.0;
			 num1++;
		 }
		 else
		 {
		      pp[2] += blackPoint[k].x*1.0;
		      pp[3] += blackPoint[k].y*1.0;
			  num2++;
		 }
	}

	pp[0] = pp[0]/num1;
	pp[1] = pp[1]/num1;

	pp[2] = pp[2]/num2;
	pp[3] = pp[3]/num2;
*/
 
	for(i=0;i<50;i++)
	{
	  x[i] = blackPoint[100+i].x;
	  y[i] = blackPoint[100+i].y;

	}
    deal();//采用克莱默法则求解方程
  //  printf("经最小二乘法拟合得到的一元线性方程为:\n"); 
	//	printf("f(x)=%3.3fx+%3.3f\n",a1,a0); 
    tmp.Format("经最小二乘法拟合得到的一元线性方程为:f(x)=%3.3fx+%3.3f",a1,a0);
	MessageBox(tmp);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/430359.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣经典题目解析--删除链表的倒数第 N 个结点

原题地址:. - 力扣&#xff08;LeetCode&#xff09; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;h…

【韩顺平零基础学java】第12章课后题

练习题1 如果用户输入的不是一个整数&#xff0c;就提示他反复输入&#xff0c;直到输入的是一个整数为止 import java.util.Scanner;/*如果用户输入的不是一个整数&#xff0c;就反复输入&#xff0c;直到输入的是一个整数为止*/ public class TryCatchExercise04 {public s…

代码随想录算法训练营Day37 | LeetCode738.单调递增的数字、LeetCode968.监控二叉树、贪心算法总结

LeetCode738.单调递增的数字 思路&#xff1a;与分糖果的题目同理&#xff0c;因为需要与前一位数比较&#xff0c;并且修改这两个数&#xff0c;因此需要从后往前遍历&#xff0c;当前一位数比当前数大时&#xff0c;则前一个数-1&#xff0c;后一个数变为9。 代码细节&…

金三银四,程序员如何备战面试季

金三银四&#xff0c;程序员如何备战面试季 一个人简介二前言三面试技巧分享3.1 自我介绍 四技术问题回答4.1 团队协作经验展示 五职业规划建议5.1 短期目标5.2 中长期目标 六后记 一个人简介 &#x1f3d8;️&#x1f3d8;️个人主页&#xff1a;以山河作礼。 &#x1f396;️…

【数据存储】大端存储||小端存储(超详细解析,小白一看就懂!!!)

目录 一、前言 二、什么是低地址、高地址 &#xff1f; 三、什么是数据的高位和低位 &#xff1f; 四、什么是大小端存储&#xff1f; &#x1f349; 小端存储详解 &#x1f352; 大端存储详解 五、为什么会有大小端存储&#xff1f; &#x1f34d;大端存储的优点 &#…

跨境电商趋势解析:社交电商携手私域流量运营,精准触达与转化

随着全球化的深入发展&#xff0c;跨境电商逐渐成为全球贸易的重要组成部分。在这一背景下&#xff0c;社交电商作为一种新兴的商业模式&#xff0c;正逐渐在跨境电商领域崭露头角&#xff0c;并对私域流量的运营产生了深远的影响。本文Nox聚星将和大家分析社交电商在跨境电商中…

数据结构(一)综述

一、常见的数据结构 数据结构优点缺点数组查找快增删慢链表增删快查找慢哈希表增删、查找都快数据散列&#xff0c;对存储空间有浪费栈顶部元素插入和取出快除顶部元素外&#xff0c;存取其他元素都很慢队列顶部元素取出和尾部元素插入快存取其他元素都很慢二叉树增删、查找都快…

交叉编译qt5.14.2

qt源码下载地址&#xff1a;qt-everywhere-src-5.14.2.tar.xz 1.修改qt-everywhere-src-5.14.2/qtbase/mkspecs/linux-arm-gnueabi-g/qmake.conf文件&#xff1a; # # qmake configuration for building with arm-linux-gnueabi-g #MAKEFILE_GENERATOR UNIX CONFIG …

Guitar Pro 8.1中文版永久许可证激活2024最新24位注册激活码生成器

Guitar Pro是一款非常受欢迎的音乐制作软件&#xff0c;它可以帮助用户创建和编辑各种音乐曲谱。从其诞生以来就送专门为了编写吉他谱而研发迭代的。 尽管这款产品可能已经成为全球最受欢迎的吉他打谱软件&#xff0c;在编写吉他六线谱和乐队总谱中始终处于行业领先地位&#…

返回静态数据

在Java项目中&#xff0c;往往不会一直返回某某数据&#xff0c;而是会返回一个静态页面&#xff0c;那么&#xff0c;如何正确返回一个静态页面呢&#xff1f;&#xff1f; 要想成功的返回一个静态页面前提是必须要有一个静态页面&#xff1a; <!DOCTYPE html> <ht…

GEE 数据集 ——利用leafmap python软件包实现NASA数据的接入(colab示例)

我们如何获取我们想要的数据,这里我们通过 leafmap python软件包实现NASA数据种全球超过9000+的数据集产品的接入和使用。这里我们使用在线的colab来实现处理,因为这里我们可以很好的应用已经在线配置好的colab环境来实现,省去了安装过程的繁琐。 要下载和访问数据,您需要…

rust学习(tokio协程分析一)

代码&#xff1a; async fn doAsyncPrint(v:u32) {println!("start doAsyncPrint,v is {},tid is {:?}",v,system::myTid());//thread::sleep(Duration::from_secs(1));time::sleep(Duration::from_secs(10)).await;println!("end,v is {},tid is {:?}"…

MacOS开发环境搭建

MacOS开发环境搭建 一、MacOS二、Python三、MacOS搭建Python开发环境1.Python下载地址1.1 Python官网地址1.2 Python下载地址 2.安装Python3.安装Python4.安装PyCharm5.创建一个Python项目6.配置PyCharm7.安装Python包8.运行Python代码9.总结 一、MacOS macOS是一套由苹果开发的…

云原生数据库 GaiaDB 支持新的管理工具啦

GaiaDB 是百度智能云自研的新一代企业级关系型数据库&#xff0c;最大容量可扩展 500TB 以上&#xff0c;吞吐达到 150 万以上 QPS。 作为一款 100% 兼容 MySQL 的云原生数据库产品&#xff0c;用户可以通过多种客户端工具连接 GaiaDB 实例&#xff0c;例如 MySQL Workbench、N…

【产品经理方法论——产品的基本概念】

1. 产品学三元素 产品学有三个元素&#xff1a;用户、需求、产品 产品学的内容&#xff1a;根据用户的需求设计产品&#xff0c;使用产品服务用户 仅仅通过三个元素无法说明每个元素的概念&#xff0c;因为三个元素互为说明关系。 通过引入人/群体来说明三个元素的关系。 需…

全局渐变滚动条样式

效果如下&#xff1a; APP.vue<style> /* 整个滚动条 */ ::-webkit-scrollbar {width: 5px;height: 10px; } /* 滚动条上的滚动滑块 */ ::-webkit-scrollbar-thumb {background-color: #49b1f5;/* 关键代码 */background-image: -webkit-linear-gradient(45deg,rgba(255,…

Svg Flow Editor 原生svg流程图编辑器(一)

效果展示 项目概述 svg flow editor 是一款流程图编辑器&#xff0c;提供了一系列流程图交互、编辑所必需的功能&#xff0c;支持前端研发自定义开发各种逻辑编排场景&#xff0c;如流程图、ER 图、BPMN 流程等。 目前也有比较好的流程图设计框架&#xff0c;但是还是难满足项目…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:隐私遮罩)

用于对组件内容进行隐私遮罩处理。 说明&#xff1a; 从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 obscured obscured(reasons: Array<ObscuredReasons>) 设置组件内容的遮罩类型。 系统能力&#xff1a; Sys…

拓尔微代理商 TMI3252T 600kHz 18V 2A同步COT降压转换器

TMI3252/S/T是高效率600kHz&#xff0c;恒定导通时间 &#xff08;COT&#xff09; 控制同步模式降压型DC-DC转换器&#xff0c;能够提供高达2A电流。TMI3252/S/T集成主要具有极低 RDS&#xff08;ON&#xff09; 的开关和同步开关以尽量减少传导损耗。低输出电压纹波和小尺寸的…

E8-写了一个方法,处理一个表单里有多组需要实现单选或复选的复选框

起因 今天同事发来需求&#xff0c;要做一个工作流&#xff0c;其中表单里有几组选项。在纸质单上是留出位置画勾选择的。简单的聊了一下对填报的要求&#xff0c;要求有的组要控制单选&#xff0c;有的组还不需要制多选。用文字来描述很晦涩&#xff0c;看到表单估计小伙伴们…