www.gusucode.com > VC++牛顿法解方程之混沌情况图形示例源代码源码程序 > VC++牛顿法解方程之混沌情况图形示例源代码源码程序\code\Global.cpp
//Download by http://www.NewXing.com // Global.cpp: implementation of the CGlobal class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Faction.h" #include "Global.h" #include <math.h> #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif CGlobal G; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CGlobal::CGlobal() { m_bESCStop=FALSE; m_rgbBackground = RGB(0,0,0); } CGlobal::~CGlobal() { } /* Option Explicit '====================================================================== '一些 API 调用 和 封装的调用函数 '====================================================================== 'API '用指定颜色绘制一个点 Public Declare Function SetPixelV Lib "gdi32" _ (ByVal hdc As Long, ByVal x As Long, _ ByVal y As Long, ByVal crColor As Long) As Long '用指定颜色绘制一个点,并返回实际设置的值 Public Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long '获得指定点的颜色值 Public Declare Function GetPixel Lib "gdi32" _ (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long '程序暂停指定时间 Public Declare Sub Sleep Lib "kernel32" _ (ByVal dwMilliseconds As Long) '获取图片像素编码性质 Public Declare Function GetPixelFormat Lib "gdi32" (ByVal hdc As Long) As Long Public Type PIXELFORMATDESCRIPTOR '像素性质设置时使用 nSize As Integer nVersion As Integer dwFlags As Long iPixelType As Byte cColorBits As Byte cRedBits As Byte cRedShift As Byte cGreenBits As Byte cGreenShift As Byte cBlueBits As Byte cBlueShift As Byte cAlphaBits As Byte cAlphaShift As Byte cAccumBits As Byte cAccumRedBits As Byte cAccumGreenBits As Byte cAccumBlueBits As Byte cAccumAlphaBits As Byte cDepthBits As Byte cStencilBits As Byte cAuxBuffers As Byte iLayerType As Byte bReserved As Byte dwLayerMask As Long dwVisibleMask As Long dwDamageMask As Long End Type '设置图片像素编码方式 Public Declare Function SetPixelFormat Lib "gdi32" (ByVal hdc As Long, ByVal N As Long, pcPixelFormatDescriptor As PIXELFORMATDESCRIPTOR) As Long Public Const SWP_NOMOVE = &H2 Public Const HWND_TOPMOST = -1 Public Const SWP_NOSIZE = &H1 Public Const SWP_NOACTIVATE = &H10 Public Const HWND_NOTOPMOST = -2 'API 用来实现设置顶层窗口 Public Declare Function SetWindowPos Lib "user32" _ (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _ ByVal x As Long, ByVal y As Long, _ ByVal cx As Long, ByVal cy As Long, _ ByVal wFlags As Long) As Long 'API Public Const SW_NORMAL = 1 '外部调用 Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long Public Const SPIF_SENDWININICHANGE = &H2 Public Const SPIF_UPDATEINIFILE = &H1 Public Const SPI_SETDESKWALLPAPER = 20 '设置桌面用 Public Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" _ (ByVal uAction As Long, _ ByVal uParam As Long, _ ByRef lpvParam As Any, _ ByVal fuWinIni As Long) As Long '获得Windows所在目录名称 Public Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" _ (ByVal lpBuffer As String, _ ByVal nSize As Long) As Long '获得图像数据 Public Declare Function GetBitmapBits Lib "gdi32" _ (ByVal hBitmap As Long, _ ByVal dwCount As Long, _ lpBits As Any) As Long '设置图像数据 Public Declare Function SetBitmapBits Lib "gdi32" _ (ByVal hBitmap As Long, _ ByVal dwCount As Long, _ lpBits As Any) As Long Public Sub SetWallPaper(PicBox As PictureBox) '设置桌面图片 Dim fileName As String, temp As String Dim i As Long, k As Long temp = String(255, 0) GetWindowsDirectory temp, 256 temp = Left(temp, InStr(1, temp, Chr(0)) - 1) If Right(temp, 1] = "\" Then temp = Left(temp, Len(temp) - 1) fileName = temp + "\HssNiuDunWallPaper.bmp" SavePicture PicBox.Image, fileName DoEvents 'Call ClearWallPaper Call SetWallPaperA(fileName) End Sub Public Sub ClearWallPaper() '清除桌面图片 Dim temp As Long temp = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0&, ByVal "(None)", _ SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE) 'MsgBox temp End Sub Public Sub SetWallPaperA(BitmapFile As String) '设置桌面图片API调用 Dim temp As Long temp = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0&, ByVal BitmapFile, _ SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE) 'MsgBox temp 'SystemParametersInfo SPI_SETDESKWALLPAPER, 0, ByVal BMPFile, SPIF_UPDATEINIFILE End Sub '======================================================= */ //SetPixelV SetPixel GetPixel //Sleep //GetPixelFormat //SetPixelFormat PIXELFORMATDESCRIPTOR //SetWindowPos //ShellExecute //SystemParametersInfo //GetWindowsDirectory //GetBitmapBits //SetBitmapBits void CGlobal::SetWallPaper()//PicBox As PictureBox) { //设置桌面图片 CString cs, cs1, fileName; char temp[_MAX_PATH]; GetWindowsDirectory(temp, _MAX_PATH); cs = temp; cs1 = cs.Right(1); int len=cs.GetLength(); if( !cs1.CompareNoCase("\\") ) cs = cs.Left(len-1); fileName = cs + "\\HssNiuDunWallPaper.bmp"; //SavePicture PicBox.Image, fileName ; //DoEvents //Call ClearWallPaper SetWallPaperA((char *&)fileName); } void CGlobal::ClearWallPaper() { //清除桌面图片 int temp; temp = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_UPDATEINIFILE|SPIF_SENDWININICHANGE); //MsgBox temp //AfxMessagegBox(); } void CGlobal::SetWallPaperA(char* pBmpFile) { //设置桌面图片API调用 int temp; temp = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pBmpFile, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); //MsgBox temp //SystemParametersInfo SPI_SETDESKWALLPAPER, 0, ByVal BMPFile, SPIF_UPDATEINIFILE } /* Option Explicit '====================================================================== '控制参数的定义、基本操作函数 和 Min()、Max()函数 '====================================================================== '控制参数表 Public Const SeDataLen As Long = 200 Public SeData(-2 To SeDataLen, 0 To 19) As Double ' 23组参数,每组19个参数值 ' SeData(0,i)组 为初始值 ' SeData(-1,i)或SeData(-2,i) 为临时值 ' SeData(i,0)=1标志该组有效 ' PSeData“指向”控制参数数组,以决定上一幅或下一幅图像的参数在数组中的位置 Public PSeData As Long '控制参数压入 Public Sub SeDataIN() Dim i As Long Dim j As Long For i = SeDataLen - 2 To 0 Step -1 For j = 0 To 19 SeData(i + 1, j] = SeData(i, j) Next j Next i SeData(1, 5] = 0 End Sub '控制参数弹出 Public Sub SeDataOUT() Dim i As Long Dim j As Long For i = 1 To SeDataLen - 1 For j = 0 To 19 SeData(i - 1, j] = SeData(i, j) Next j Next i SeData(0, 5] = 0 End Sub '最小值 Public Function Min(x0 As Single, x1 As Single) As Single If x0 > x1 Then Min = x1 Else Min = x0 End If End Function '最大值 Public Function Max(x0 As Single, x1 As Single) As Single If x0 < x1 Then Max = x1 Else Max = x0 End If End Function '======================================================= */ //控制参数表 //#define SEDATALEN 200 //#define SEDATANUM 20 //double SeData0[2][SEDATANUM]; // SeData0(0,i)或SeData(1,i) 为临时值 //double SeData[SEDATALEN][SEDATANUM]; // 23组参数,每组19个参数值 // SeData(0,i)组 为初始值 // SeData(i,0)=1标志该组有效 //' PSeData“指向”控制参数数组,以决定上一幅或下一幅图像的参数在数组中的位置 //Public PSeData As Long //控制参数压入 void CGlobal::SeDataIN() { for(int i=SEDATALEN-2; i>=0; i--) memcpy(&m_dSeData[i+1], &m_dSeData[i], SEDATANUM*sizeof(double)); m_dSeData[1][5] = 0; } //控制参数弹出 void CGlobal::SeDataOUT() { for(int i=1; i<SEDATALEN; i++) memcpy(&m_dSeData[i-1], &m_dSeData[i], SEDATANUM*sizeof(double)); m_dSeData[0][5] = 0; } // __min(); // __max(); //====================================================================== //实现不同方程的牛顿迭代法 和 一些基本复变函数 //====================================================================== //+++++++++++实现不同方程的牛顿迭代法,并返回方程的各种基本性质+++++++++++++ int CGlobal::MMi(double x0, double y0, int nN, int M, int nM, double* Hx, double* Hy, double* dL1, double* dL2, double* dL3, double* dL4) //调用时MMi(x0, y0, Int(SeData(0, 13)), M, nM, dX, dY, dL1, dL2, dL3, dL4) // 牛顿迭代法解方程原理: // 不失一般性设方程为: f(Z] = 0 (关于复数Z的函数) // 对 f(Z) 求导函数得: f//(Z) // 对任意复数Z0可以有Z1 , Z1 = Z0 - f(Z0)/f//(Z0) // 同样,对复数Z1可以有Z2 , Z2 = Z1 - f(Z1)/f//(Z1) // …… …… …… // 则,有迭代式:Z(n+1)=Z(n)-f(Z(n))/f//(Z(n)) // 对于选定的起始点,迭代大多都会收敛于方程f(z] = 0 的某个根, // 这就是牛顿迭代法解方程的基本方式; // 但也可能存在许多点,使迭代根本就不会收敛, // 甚至可能出现混沌的状态。 //nN 方程序号(>=1, 整数) // M 迭代次数 //nM 最大迭代次数 //dX 第一次迭代x轴的变化率 //dY 第一次迭代y轴的变化率 //dL1 第一次迭代移动距离 //dL2 第nM次迭代移动距离 //dL3 第nM次迭代距离(0,0)点的距离 //dL4 迭代得到解以后距离解的大概距离 { int i, k=0; double x1, x2, y1, y2, m0; double SeTa1, P1, A; // double SeTa2, P2, B; double temp0, temp1, temp2, temp3=0, temp4=0; double temp5, temp6, temp7, temp8;//, temp9; double R1, R2, N7; double bx, by;//, xb, yb; int N, ret; int nSum; //nSum值用来判断迭代是否已经到达根(方程的解),这是一种比较好的方式 //On Error GoTo aaa: x1 = x0; y1 = y0; N = int(m_dSeData[0][14]); N7 = 0.01; nSum = 0; switch(nN) { case 1: //方程 Z^N-1=0 for( i=1; i<=M; i++) { P1 = sqrt(x1*x1 + y1*y1); SeTa1 = ZArg(x1, y1, 0); x2 = ((N-1)*P1*cos(SeTa1) + pow(P1, 1-N)*cos((1-N)*SeTa1))/N; y2 = ((N-1)*P1*sin(SeTa1) + pow(P1, 1-N)*sin((1-N)*SeTa1))/N; temp0 = pow(fabs(fabs(x1)-fabs(x2)),2) + pow(fabs(fabs(y1)-fabs(y2)),2); if(temp0 < N7){ nSum++; if(nSum > 2){ *dL4 = temp0 / N7; if(i > nM){ break; } } } if(i == 1){ *Hx = fabs(x1 - x2); *Hy = fabs(y1 - y2); *dL1 = pow((*Hx)*(*Hx)+(*Hy)*(*Hy), 0.5); } if(i == nM){ *dL2 = pow((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2), 0.5); *dL3 = pow(x2*x2+y2*y2, 0.5); } x1 = x2; y1 = y2; } ret = (k-1)*M/N+i; break; case 0: //方程 Z^3-1=0 的特解 case 2: //方程 Z^3-1=0 的特解 x1 = -x1; //其实没有必要,这里做了一下水平翻转 for(i=1; i<=M; i++) { x2 = x1; y2 = y1; m0 = pow((x1*x1 + y1*y1), 2); if(pow((x1*x1*x1-x1*y1*y1*3-1),2) + pow((x1*x1*y1*3-y1*y1*y1),2) < N7 ) { *dL4 = fabs(sqrt(x1*x1 + y1*y1) - 1) / N7; if(i>nM) break; } x1 = x2 - (x2+y2)/6 + (x2*x2 - y2*y2 - x2*y2*2)/6/m0; y1 = y2 + (x2-y2)/6 + (y2*y2 - x2*x2 - x2*y2*2)/6/m0; if(i==1){ *Hx = fabs(x1 - x2); *Hy = fabs(y1 - y2); *dL1 = pow((*Hx)*(*Hx) + (*Hy)*(*Hy), 0.5); } if(i==nM){ *dL2 = pow((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2), 0.5); *dL3 = pow(x1*x1 + y1*y1, 0.5); } } if(x1 > 0.9) ret = (int)(i + 1 * 0.33 * M); else if(y1 > 0.8) ret = (int)(i + (0.33 + 1 * 0.33) * M); else if(y1 < -0.8) ret = (int)(i + (0.66 + 0.33 * 1) * M); break; case 3: //方程 Z*(1+Z^A)/(1-Z^A)=R bx = x0; by = y0; A = m_dSeData[0][15]; //: B = SeData(0, 16) R1 = m_dSeData[0][17]; R2 = m_dSeData[0][18]; for(i=1; i<=M; i++) { temp1 = bx; temp2 = by; Zfang(temp1, temp2, A, &temp3, &temp4); Zji(temp3, temp4, temp1, temp2, &temp5, &temp6); Zji(temp3, temp4, R1, R2, &temp7, &temp8); temp5 += temp7 - R1 + temp1; temp6 += temp8 - R2 + temp2; Zshang(temp3, temp4, temp1, temp2, &temp7, &temp8); temp7 += 1 + (A + 1) * temp3; temp8 += (A + 1) * temp4; Zshang(temp5, temp6, temp7, temp8, &temp3, &temp4); bx = temp1 - temp3; by = temp2 - temp4; temp0 = pow(fabs(fabs(bx)-fabs(temp1)), 2) + pow(fabs(fabs(by)-fabs(temp2)), 2); if(temp0 < N7){ nSum++; if(nSum > 2){ *dL4 = temp0 / N7; if(i > nM) break; } } if(i==1){ *Hx = fabs(bx - temp1); *Hy = fabs(by - temp2); *dL1 = pow(((*Hx)*(*Hx) + (*Hy)*(*Hy)), 0.5); } if(i==nM){ *dL2 = pow(((bx-temp1)*(bx-temp1) + (by-temp2)*(by-temp2)), 0.5); *dL3 = pow((bx*bx + by*by), 0.5); } } ret = i; break; case 4: /* { // 曼德勃罗特集的数学模型非常简单。假设有复数Z和μ,用下式 //迭代计算:Z=Z2+μ,由于μ的取值不同,经过若干次数迭代以后Z //的幅值可能趋向无穷,也可能保持有界,曼德勃罗特集就是那些使 //Z保持有界的μ的集合,把μ在复平面上的分布作成图像,就像这里 //演示的那样具有极其复杂的结构。 int nThre=100; //nThre代表设置的门限值,当迭代后Z的幅值的平方大于nThre则认为趋于无穷 // int xCord,yCord; //xCord和yCord分别代表平面上的点的坐标位置 int nColor,nTimes;//nColor代表作图时所使用的颜色,nTimes表示迭代的次数 float reP,rePmin=-1.5,rePmax=0.75; //reP表示由平面上一点所代表的μ值的实部,rePmax、rePmin分别代表μ值实部可取的最大值和最小值 float imP,imPmin=-1.5,imPmax=1.5; //imP、imPmax和imPmin分别代表μ的虚部及其容许的最大值和最小值 float reZ,imZ; //reZ和imZ分别代表Z值的实部和虚部 float deltImP,deltReP;//,deltImP、deltReP表示每一个象素代表的实部和虚部值的大小 float absZ; //absZ代表Z值的幅值 float tmpReZ; rePmin=(float)G.m_dSeData[0][1]; imPmin=(float)G.m_dSeData[0][2]; rePmax=(float)G.m_dSeData[0][3]; imPmax=(float)G.m_dSeData[0][4]; //计算屏幕上一个像素表示的实部和虚部值的大小 deltReP=(rePmax-rePmin)/G.m_dwWidth ; deltImP=(imPmax-imPmin)/G.m_dwHeight; //计算屏幕上一点所代表的μ值大小 reP=rePmin+deltReP*x0; imP=imPmin+deltImP*y0; reZ=0; imZ=0; for(nTimes=0;nTimes<M;nTimes++)//160 { tmpReZ=reZ*reZ-imZ*imZ+reP; //计算迭代后的Z imZ=2*reZ*imZ+imP;//值及其幅值大小 reZ=tmpReZ; absZ=reZ*reZ+imZ*imZ; if (absZ>nThre) { //nColor=nTimes/10; break; } //如果幅值的平方大于门限值终止迭代 //nColor=0; } *Hx = reZ; *Hy = imZ; *dL1= absZ; }*/ break; } return ret; // Exit Function //aaa: // ret = i; } int CGlobal::MDBLT(int x0, int y0) { // 曼德勃罗特集的数学模型非常简单。假设有复数Z和μ,用下式 //迭代计算:Z=Z2+μ,由于μ的取值不同,经过若干次数迭代以后Z //的幅值可能趋向无穷,也可能保持有界,曼德勃罗特集就是那些使 //Z保持有界的μ的集合,把μ在复平面上的分布作成图像,就像这里 //演示的那样具有极其复杂的结构。 // 曼德勃罗特集的数学模型非常简单。假设有复数Z和μ,用下式 //迭代计算:Z=Z2+μ,由于μ的取值不同,经过若干次数迭代以后Z //的幅值可能趋向无穷,也可能保持有界,曼德勃罗特集就是那些使 //Z保持有界的μ的集合,把μ在复平面上的分布作成图像,就像上 //面演示的那样具有极其复杂的结构。 int nThre=10000000;//100; //nThre代表设置的门限值,当迭代后Z的幅值的平方大于nThre则认为趋于无穷 // int xCord,yCord; //xCord和yCord分别代表平面上的点的坐标位置 int nColor,nTimes;//nColor代表作图时所使用的颜色,nTimes表示迭代的次数 float reP,rePmin=-1.5,rePmax=0.75; //reP表示由平面上一点所代表的μ值的实部,rePmax、rePmin分别代表μ值实部可取的最大值和最小值 float imP,imPmin=-1.5,imPmax=1.5; //imP、imPmax和imPmin分别代表μ的虚部及其容许的最大值和最小值 float reZ,imZ; //reZ和imZ分别代表Z值的实部和虚部 float deltImP,deltReP;//,deltImP、deltReP表示每一个象素代表的实部和虚部值的大小 float absZ; //absZ代表Z值的幅值 float tmpReZ; rePmin=(float)G.m_dSeData[0][1]; imPmin=(float)G.m_dSeData[0][2]; rePmax=(float)G.m_dSeData[0][3]; imPmax=(float)G.m_dSeData[0][4]; //计算屏幕上一个像素表示的实部和虚部值的大小 deltReP=(rePmax-rePmin)/G.m_dwWidth ; deltImP=(imPmax-imPmin)/G.m_dwHeight; //计算屏幕上一点所代表的μ值大小 reP=rePmin+deltReP*x0; imP=imPmin+deltImP*y0; reZ=0; imZ=0; for(nTimes=0;nTimes<256;nTimes++)//160 { tmpReZ=reZ*reZ-imZ*imZ+reP; //计算迭代后的Z imZ=2*reZ*imZ+imP;//值及其幅值大小 reZ=tmpReZ; absZ=reZ*reZ+imZ*imZ; if (absZ>nThre) { nColor=nTimes*10;// /10; if(nColor>255) nColor%=256; break; } //如果幅值的平方大于门限值终止迭代 nColor=0; } return nColor; // 上面的程序中,可以通过改变imPmin、imPmax以及rePmin与rePmax的值 //来对图像的局部细节进行放大,从而可以观察到更加精美复杂的图像,领悟 //分形图像的神韵。 // 曼德勃罗特集是人们发现的最早的分形图形之一,也是人们研究最多的 //分形图形之一,今年的菲尔兹奖(数学界的最高奖)得主麦克马兰就是因为 //在曼德勃罗特集研究中的成绩而获此殊荣的。这些年关于分形的研究已经渗 //透到科学领域的各个学科,在计算机领域利用分形的方法来对自然景物进行 //逼真的模拟是一个很具挑战性的研究方向。 // (兰州大学2041信箱 梁昌霖 730000) } //一些复变函数 //============================ //Z1^Z2 (复数的复数次方) void CGlobal::ZZFang(double x1, double y1, double x2, double y2, double k, double* pX, double* pY) { double T, TT; double P, Fai; // On Error Resume Next P = sqrt(x1 * x1 + y1 * y1); if( !P){ *pX = 0; *pY = 0; return; } Fai = ZArg(x1, y1, k); T = pow(P,x2) * exp(-y2 * Fai); TT = log(P) * y2 + x2 * Fai; *pX = T * cos(TT); *pY = T * sin(TT); } //Z1*Z2 (复数乘积) void CGlobal::Zji(double x1, double y1, double x2, double y2, double* pX, double* pY) { *pX = x1*x2 - y1*y2; *pY = x1*y2 + y1*x2; } //Z1/Z2 (复数商) void CGlobal::Zshang(double x1, double y1, double x2, double y2, double* pX, double* pY) { double T; T = x2*x2 + y2*y2; if(!T){ if( !x1){ *pX = 1; *pY = 1; } else{ *pX = (x1>0 ? 1 : (x1<0 ? -1 : 0)) * 1E+50; *pY = (y1>0 ? 1 : (y1<0 ? -1 : 0)) * 1E+50; } } else{ *pX = (x1*x2 + y1*y2) / T; *pY = (-x1*y2 + y1*x2) / T; } } //Z^N (复数的实数次方) void CGlobal::Zfang(double x1, double y1, double N, double* pX, double* pY) { double T, TT, AtnYX; T = sqrt(x1 * x1 + y1 * y1); AtnYX = atan2(y1, x1); if(x1 < 0) TT = PI + AtnYX; else if(y1 > 0) TT = AtnYX; else //if y1<=0 then TT = PI * 2 + AtnYX;//2# T = pow(T,N); TT = TT * N; *pX = T * cos(TT); *pY = T * sin(TT); } //Arg(Z) (复数的辐角) double CGlobal::ZArg(double x, double y, double k) { double ret=0; if(!x){ if(!y) ret = 0; else if(y > 0) ret = PI / 2;//2# else //if y<0 then ret = PI * 1.5; } else if(x>0){ ret = atan2(y, x); if(ret < 0) ret = PI * 2 + ret; } else //if x<0 then ret = atan2(y, x) + PI; ret = ret + PI * 2 * k; return ret; } //为了实现 Mandelbrot(曼德勃罗特集) 特效定义的函数 (其实就是Mandelbrot函数迭代) void CGlobal::fz2(double x0, double y0, double xx, double yy, double* pX, double* pY, int N) {//Z=Z2+μ double t1, t2, t3, t4; int i; t1 = x0; t2 = y0; for(i=1; i<=N; i++){ t3 = t1 * t1 - t2 * t2 + xx; t4 = 2 * t1 * t2 + yy; t1 = t3; t2 = t4; } *pX = t1; *pY = t2; } //======================================================= /* Option Explicit '====================================================================== '图像数据RGB调整的基本函数 和 一些变量定义 '====================================================================== Public PicDataOld() As Byte '实现RGB调整时用来保存原图像的数据 Public PicDataNew() As Byte '实现RGB调整时用来保存调整后的图像的数据 Public PicLeng As Long '实现RGB调整时用来保存图像数据的长度(字节) Public PicBit As Long '实现RGB调整时用来保存图像的颜色位数 Public m_dRGBTime As Double '++++++++++++更改图像RGB数据++++++++++++++ Public Sub EditRGB(RGBData0() As Byte, RGBData1() As Byte, dLeng As Long, PicBit As Long, dR As Long, dG As Long, dB As Long, RGBTimeNow As Double) '更改图像RGB数据(不考虑256色和16色) Dim i As Long Dim temp As Long Dim tempR As Long Dim tempG As Long Dim tempB As Long Dim tempColor As Long '如果把图片的颜色位数一早定为24位,则程序将变得很好处理,而且还有很多其他好处... Select Case PicBit Case 32 '32位色深 For i = 0 To dLeng - 1 Select Case (i Mod 4) Case 0 temp = RGBData0(i) + dB Case 1 temp = RGBData0(i) + dG Case 2 temp = RGBData0(i) + dR Case 3 temp = RGBData0(i) '透明度,一般给0就可以了 End Select If temp > 255 Then temp = 255 ElseIf temp < 0 Then temp = 0 End If RGBData1(i] = temp If i Mod 50 = 0 Then DoEvents If RGBTimeNow <> m_dRGBTime Then Exit Sub End If End If Next i Case 24 '24位色深 For i = 0 To dLeng - 1 Select Case (i Mod 3) Case 0 temp = RGBData0(i) + dB Case 1 temp = RGBData0(i) + dG Case 2 temp = RGBData0(i) + dR End Select If temp > 255 Then temp = 255 ElseIf temp < 0 Then temp = 0 End If RGBData1(i] = temp If i Mod 50 = 0 Then DoEvents If RGBTimeNow <> m_dRGBTime Then Exit Sub End If End If Next i Case 16 '16位色深在某些机子上可能有问题,因为16位色编码方式是由硬件厂商决定的: '大部分机子采用的编码方式:R:9-13,G:14-16,1-3,B:4-8 (5,6,5) '某些机子上可能为 R:10-14,G:15-16,1-3,B:4-8,空(或作为是否透明标志):9 (5,5,5,1) '还有的机子为:R:9-14,G:15-16,1-3,B:4-8 (6,5,5) '由于没有查到相关资料(API函数:GetPixelFormat()和SetPixelFormat()),望高手指教: HouSisong@263.net tempColor = HGetPixelFormat(frmMain.Picture1) '自己编的替代函数,16位色时返回具体编码方式。 If tempColor = 565 Then '默认方式 R:9-13,G:14-16,1-3,B:4-8 For i = 0 To dLeng \ 2 - 1 tempB = RGBData0(2 * i) Mod 32 tempG = RGBData0(2 * i) \ 32 + (RGBData0(2 * i + 1) Mod 8) * 8 tempR = RGBData0(2 * i + 1) \ 8 tempB = tempB + dB * 5 \ 8 tempG = tempG + dG * 5 \ 8 tempR = tempR + dR * 5 \ 8 If tempB > 31 Then tempB = 31 ElseIf tempB < 0 Then tempB = 0 End If If tempG > 63 Then tempG = 63 ElseIf tempG < 0 Then tempG = 0 End If If tempR > 31 Then tempR = 31 ElseIf tempR < 0 Then tempR = 0 End If RGBData1(2 * i] = tempB + 32 * (tempG Mod 8) RGBData1(2 * i + 1] = tempG \ 8 + tempR * 8 If i Mod 50 = 0 Then DoEvents If RGBTimeNow <> m_dRGBTime Then Exit Sub End If End If Next i ElseIf tempColor = 5551 Then ' R:10-14,G:15-16,1-3,B:4-8,空:9 For i = 0 To dLeng \ 2 - 1 temp = RGBData0(2 * i + 1) \ 128 tempB = RGBData0(2 * i) Mod 32 tempG = RGBData0(2 * i) \ 32 + (RGBData0(2 * i + 1) Mod 4) * 8 tempR = (RGBData0(2 * i + 1) Mod 128) \ 4 tempB = tempB + dB * 5 \ 8 tempG = tempG + dG * 5 \ 8 tempR = tempR + dR * 5 \ 8 If tempB > 31 Then tempB = 31 ElseIf tempB < 0 Then tempB = 0 End If If tempG > 31 Then tempG = 31 ElseIf tempG < 0 Then tempG = 0 End If If tempR > 31 Then tempR = 31 ElseIf tempR < 0 Then tempR = 0 End If RGBData1(2 * i] = tempB + 32 * (tempG Mod 8) RGBData1(2 * i + 1] = tempG \ 8 + tempR * 4 + temp * 128 If i Mod 50 = 0 Then DoEvents If RGBTimeNow <> m_dRGBTime Then Exit Sub End If End If Next i ElseIf tempColor = 655 Then 'R:6,G:5,B:5 '没有处理代码 '我在几台电脑上只测到了上面两种情况,这里留给读者解决 End If End Select End Sub '16位色时返回图片具体编码方式 Public Function HGetPixelFormat(Pic As PictureBox) As Long '由于没有查到相关资料(GetPixelFormat()和SetPixelFormat()),望高手指教: HouSisong@263.net '其实可以向屏幕绘制一个指定颜色,然后返回实际绘制的颜色值来判断颜色编码方式。 '这里留给读者解决 HGetPixelFormat = 565 End Function '======================================================= */ //BYTE PicDataOld[]; //实现RGB调整时用来保存原图像的数据 //BYTE PicDataNew[]; //实现RGB调整时用来保存调整后的图像的数据 //int PicLeng; //实现RGB调整时用来保存图像数据的长度(字节) //int PicBit; //实现RGB调整时用来保存图像的颜色位数 //double m_dRGBTime; //++++++++++++更改图像RGB数据++++++++++++++ void CGlobal::EditRGB(BYTE* pRGBData0, BYTE* pRGBData1, int dLeng, int PicBit, int dR, int dG, int dB, double RGBTimeNow) { //更改图像RGB数据(不考虑256色和16色) int i, temp, tempR, tempG, tempB, tempColor; //如果把图片的颜色位数一早定为24位,则程序将变得很好处理,而且还有很多其他好处... switch(PicBit) { case 32: //32位色深 for(i=0; i<dLeng; i++) { switch(i%4) { case 0: temp = pRGBData0[i] + dB; break; case 1: temp = pRGBData0[i] + dG; break; case 2: temp = pRGBData0[i] + dR; break; case 3: temp = pRGBData0[i]; //透明度,一般给0就可以了 break; } if(temp > 255) temp = 255; else if(temp < 0) temp = 0; pRGBData1[i] = temp; if( !(i%50) ){ // DoEvents if(RGBTimeNow != m_dRGBTime) return; } } break; case 24: //24位色深 for(i=0; i<dLeng; i++) { switch(i%3) { case 0: temp = pRGBData0[i] + dB; break; case 1: temp = pRGBData0[i] + dG; break; case 2: temp = pRGBData0[i] + dR; break; } if(temp > 255) temp = 255; else if(temp < 0) temp = 0; pRGBData1[i] = temp; if( !(i%50) ){ // DoEvents if( RGBTimeNow != m_dRGBTime) return; } } break; case 16: //16位色深在某些机子上可能有问题,因为16位色编码方式是由硬件厂商决定的: //大部分机子采用的编码方式:R:9-13,G:14-16,1-3,B:4-8 (5,6,5) //某些机子上可能为 R:10-14,G:15-16,1-3,B:4-8,空(或作为是否透明标志):9 (5,5,5,1) //还有的机子为:R:9-14,G:15-16,1-3,B:4-8 (6,5,5) //由于没有查到相关资料(API函数:GetPixelFormat()和SetPixelFormat()),望高手指教: HouSisong@263.net tempColor = HGetPixelFormat();//frmMain.Picture1); //自己编的替代函数,16位色时返回具体编码方式。 if(tempColor == 565) //默认方式 R:9-13,G:14-16,1-3,B:4-8 { for(i=0; i<dLeng/2; i++) { tempB = pRGBData0[2*i]%32; tempG = pRGBData0[2*i]/32 + (pRGBData0[2*i+1]%8)*8; tempR = pRGBData0[2*i+1]/8; tempB = tempB+dB*5/8; tempG = tempG+dG*5/8; tempR = tempR+dR*5/8; if(tempB > 31) tempB = 31; else if(tempB < 0) tempB = 0; if(tempG > 63) tempG = 63; else if( tempG < 0) tempG = 0; if(tempR > 31) tempR = 31; else if( tempR < 0) tempR = 0; pRGBData1[2*i] = tempB + 32*(tempG%8); pRGBData1[2*i+1] = tempG/8 + tempR*8; if( !(i%50) ){ //DoEvents if(RGBTimeNow!=m_dRGBTime){ return; } } } } else if(tempColor==5551) // R:10-14,G:15-16,1-3,B:4-8,空:9 { for(i=0; i<dLeng/2; i++) { temp = pRGBData0[2*i+1]/128; tempB = pRGBData0[2*i]%32; tempG = pRGBData0[2*i]/32 + (pRGBData0[2*i+1]%4)*8; tempR = (pRGBData0[2*i+1]%128)/4; tempB = tempB + dB*5/8; tempG = tempG + dG*5/8; tempR = tempR + dR*5/8; tempB = tempB>31 ? 31 : (tempB<0 ? 0 : tempB); tempG = tempG>31 ? 31 : (tempG<0 ? 0 : tempG); tempR = tempR>31 ? 31 : (tempR<0 ? 0 : tempR); pRGBData1[2*i] = tempB + 32*(tempG%8); pRGBData1[2*i+1] = tempG/8 + tempR*4 + temp*128; if( !(i%50) ){ //DoEvents if(RGBTimeNow!=m_dRGBTime){ return; } } } } else if(tempColor == 655){ //R:6,G:5,B:5 //没有处理代码 //我在几台电脑上只测到了上面两种情况,这里留给读者解决 } } } //16位色时返回图片具体编码方式 int CGlobal::HGetPixelFormat()//Pic As PictureBox) { //由于没有查到相关资料(GetPixelFormat()和SetPixelFormat()),望高手指教: HouSisong@263.net //其实可以向屏幕绘制一个指定颜色,然后返回实际绘制的颜色值来判断颜色编码方式。 //这里留给读者解决 //HGetPixelFormat = 565; return 565; } //=======================================================