|
珞珈山水BBS →
电脑网络 →
程序人生 →
单文区文章阅读
|
| 单文区文章阅读 [返回] |
|---|
|
发信人: largestone (顽石), 信区: Programm 标 题: Re: 请教VC里的一个程序,好心人帮帮忙 发信站: BBS 珞珈山水站 (Sat Apr 16 12:35:12 2005) 【 在 lovelily (半导体) 的大作中提到: 】 : 后台处理,系统要将图片(bmp)读入到内存中,从内存中写入一个临时文件 e:\t.. : bmp : 我做了前面的(但不知对不对),后面的不知道怎么做了。 : ................... 给你这个函数库,能够读取bmp图象的几乎所有信息 建议你用READDIB();PaintDIB();来读取文件,函数如下: // ************************************************************************ // 文件名:dibapi.cpp // // DIB(Independent Bitmap) API函数库: // // PaintDIB() - 绘制DIB对象 // CreateDIBPalette() - 创建DIB对象调色板 // FindDIBBits() - 返回DIB图像象素起始位置 // DIBWidth() - 返回DIB宽度 // DIBHeight() - 返回DIB高度 // PaletteSize() - 返回DIB调色板大小 // DIBNumColors() - 计算DIB调色板颜色数目 // CopyHandle() - 拷贝内存块 // // SaveDIB() - 将DIB保存到指定文件中 // ReadDIBFile() - 重指定文件中读取DIB对象 // // DIBToPCX256() - 将指定的256色DIB对象保存为256色PCX文件 // ReadPCX256() - 读取256色PCX文件 // // ************************************************************************ #include "stdafx.h" #include "dibapi.h" #include <io.h> #include <errno.h> #include "DIBAPI.h" #include <math.h> #include <direct.h> /* * Dib文件头标志(字符串"BM",写DIB时用到该常数) */ #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B') /************************************************************************* * * 函数名称: * PaintDIB() * * 参数: * HDC hDC - 输出设备DC * LPRECT lpDCRect - 绘制矩形区域 * HDIB hDIB - 指向DIB对象的指针 * LPRECT lpDIBRect - 要输出的DIB区域 * CPalette* pPal - 指向DIB对象调色板的指针 * * 返回值: * BOOL - 绘制成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者 * SetDIBitsToDevice()来绘制DIB对象。输出的设备由由参数hDC指 * 定;绘制的矩形区域由参数lpDCRect指定;输出DIB的区域由参数 * lpDIBRect指定。 * ************************************************************************/ BOOL WINAPI PaintDIB(HDC hDC, LPRECT lpDCRect, HDIB hDIB, LPRECT lpDIBRect, CPalette* pPal) { LPSTR lpDIBHdr; // BITMAPINFOHEADER指针 LPSTR lpDIBBits; // DIB象素指针 BOOL bSuccess=FALSE; // 成功标志 HPALETTE hPal=NULL; // DIB调色板 HPALETTE hOldPal=NULL; // 以前的调色板 // 判断DIB对象是否为空 if (hDIB == NULL) { // 返回 return FALSE; } // 锁定DIB lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 找到DIB图像象素起始位置 lpDIBBits = ::FindDIBBits(lpDIBHdr); // 获取DIB调色板,并选中它 if (pPal != NULL) { hPal = (HPALETTE) pPal->m_hObject; // 选中调色板 hOldPal = ::SelectPalette(hDC, hPal, TRUE); } // 设置显示模式 ::SetStretchBltMode(hDC, COLORONCOLOR); // 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象 if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) && (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) { // 原始大小,不用拉伸。 bSuccess = ::SetDIBitsToDevice(hDC, // hDC lpDCRect->left, // DestX lpDCRect->top, // DestY RECTWIDTH(lpDCRect), // nDestWidth RECTHEIGHT(lpDCRect), // nDestHeight lpDIBRect->left, // SrcX (int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect), // SrcY 0, // nStartScan (WORD)DIBHeight(lpDIBHdr), // nNumScans lpDIBBits, // lpBits (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo DIB_RGB_COLORS); // wUsage } else { // 非原始大小,拉伸。 bSuccess = ::StretchDIBits(hDC, // hDC lpDCRect->left, // DestX lpDCRect->top, // DestY RECTWIDTH(lpDCRect), // nDestWidth RECTHEIGHT(lpDCRect), // nDestHeight lpDIBRect->left, // SrcX lpDIBRect->top, // SrcY RECTWIDTH(lpDIBRect), // wSrcWidth RECTHEIGHT(lpDIBRect), // wSrcHeight lpDIBBits, // lpBits (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo DIB_RGB_COLORS, // wUsage SRCCOPY); // dwROP } // 解除锁定 ::GlobalUnlock((HGLOBAL) hDIB); // 恢复以前的调色板 if (hOldPal != NULL) { ::SelectPalette(hDC, hOldPal, TRUE); } // 返回 return bSuccess; } /************************************************************************* * * 函数名称: * CreateDIBPalette() * * 参数: * HDIB hDIB - 指向DIB对象的指针 * CPalette* pPal - 指向DIB对象调色板的指针 * * 返回值: * BOOL - 创建成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数按照DIB创建一个逻辑调色板,从DIB中读取颜色表并存到调色板中, * 最后按照该逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样 * 可以用最好的颜色来显示DIB图像。 * ************************************************************************/ BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal) { // 指向逻辑调色板的指针 LPLOGPALETTE lpPal; // 逻辑调色板的句柄 HANDLE hLogPal; // 调色板的句柄 HPALETTE hPal = NULL; // 循环变量 int i; // 颜色表中的颜色数目 WORD wNumColors; // 指向DIB的指针 LPSTR lpbi; // 指向BITMAPINFO结构的指针(Win3.0) LPBITMAPINFO lpbmi; // 指向BITMAPCOREINFO结构的指针 LPBITMAPCOREINFO lpbmc; // 表明是否是Win3.0 DIB的标记 BOOL bWinStyleDIB; // 创建结果 BOOL bResult = FALSE; // 判断DIB是否为空 if (hDIB == NULL) { // 返回FALSE return FALSE; } // 锁定DIB lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 获取指向BITMAPINFO结构的指针(Win3.0) lpbmi = (LPBITMAPINFO)lpbi; // 获取指向BITMAPCOREINFO结构的指针 lpbmc = (LPBITMAPCOREINFO)lpbi; // 获取DIB中颜色表中的颜色数目 wNumColors = ::DIBNumColors(lpbi); if (wNumColors != 0) { // 分配为逻辑调色板内存 hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors); // 如果内存不足,退出 if (hLogPal == 0) { // 解除锁定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回FALSE return FALSE; } lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); // 设置版本号 lpPal->palVersion = PALVERSION; // 设置颜色数目 lpPal->palNumEntries = (WORD)wNumColors; // 判断是否是WIN3.0的DIB bWinStyleDIB = IS_WIN30_DIB(lpbi); // 读取调色板 for (i = 0; i < (int)wNumColors; i++) { if (bWinStyleDIB) { // 读取红色分量 lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; // 读取绿色分量 lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; // 读取蓝色分量 lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; // 保留位 lpPal->palPalEntry[i].peFlags = 0; } else { // 读取红色分量 lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; // 读取绿色分量 lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen ; // 读取红色分量 lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; // 保留位 lpPal->palPalEntry[i].peFlags = 0; } } // 按照逻辑调色板创建调色板,并返回指针 bResult = pPal->CreatePalette(lpPal); // 解除锁定 ::GlobalUnlock((HGLOBAL) hLogPal); // 释放逻辑调色板 ::GlobalFree((HGLOBAL) hLogPal); } // 解除锁定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回结果 return bResult; } /************************************************************************* * * 函数名称: * FindDIBBits() * * 参数: * LPSTR lpbi - 指向DIB对象的指针 * * 返回值: * LPSTR - 指向DIB图像象素起始位置 * * 说明: * 该函数计算DIB中图像象素的起始位置,并返回指向它的指针。 * ************************************************************************/ LPSTR WINAPI FindDIBBits(LPSTR lpbi) { return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi)); } /************************************************************************* * * 函数名称: * DIBWidth() * * 参数: * LPSTR lpbi - 指向DIB对象的指针 * * 返回值: * DWORD - DIB中图像的宽度 * * 说明: * 该函数返回DIB中图像的宽度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER * 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。 * ************************************************************************/ DWORD WINAPI DIBWidth(LPSTR lpDIB) { // 指向BITMAPINFO结构的指针(Win3.0) LPBITMAPINFOHEADER lpbmi; // 指向BITMAPCOREINFO结构的指针 LPBITMAPCOREHEADER lpbmc; // 获取指针 lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // 返回DIB中图像的宽度 if (IS_WIN30_DIB(lpDIB)) { // 对于Windows 3.0 DIB,返回lpbmi->biWidth return lpbmi->biWidth; } else { // 对于其它格式的DIB,返回lpbmc->bcWidth return (DWORD)lpbmc->bcWidth; } } /************************************************************************* * * 函数名称: * DIBHeight() * * 参数: * LPSTR lpDIB - 指向DIB对象的指针 * * 返回值: * DWORD - DIB中图像的高度 * * 说明: * 该函数返回DIB中图像的高度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER * 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。 * ************************************************************************/ DWORD WINAPI DIBHeight(LPSTR lpDIB) { // 指向BITMAPINFO结构的指针(Win3.0) LPBITMAPINFOHEADER lpbmi; // 指向BITMAPCOREINFO结构的指针 LPBITMAPCOREHEADER lpbmc; // 获取指针 lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // 返回DIB中图像的宽度 if (IS_WIN30_DIB(lpDIB)) { // 对于Windows 3.0 DIB,返回lpbmi->biHeight return lpbmi->biHeight; } else { // 对于其它格式的DIB,返回lpbmc->bcHeight return (DWORD)lpbmc->bcHeight; } } /************************************************************************* * * 函数名称: * PaletteSize() * * 参数: * LPSTR lpbi - 指向DIB对象的指针 * * 返回值: * WORD - DIB中调色板的大小 * * 说明: * 该函数返回DIB中调色板的大小。对于Windows 3.0 DIB,返回颜色数目× * RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。 * ************************************************************************/ WORD WINAPI PaletteSize(LPSTR lpbi) { // 计算DIB中调色板的大小 if (IS_WIN30_DIB (lpbi)) { //返回颜色数目×RGBQUAD的大小 return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD)); } else { //返回颜色数目×RGBTRIPLE的大小 return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); } } /************************************************************************* * * 函数名称: * DIBNumColors() * * 参数: * LPSTR lpbi - 指向DIB对象的指针 * * 返回值: * WORD - 返回调色板中颜色的种数 * * 说明: * 该函数返回DIB中调色板的颜色的种数。对于单色位图,返回2, * 对于16色位图,返回16,对于256色位图,返回256;对于真彩色 * 位图(24位),没有调色板,返回0。 * ************************************************************************/ WORD WINAPI DIBNumColors(LPSTR lpbi) { WORD wBitCount; // 对于Windows的DIB, 实际颜色的数目可以比象素的位数要少。 // 对于这种情况,则返回一个近似的数值。 // 判断是否是WIN3.0 DIB if (IS_WIN30_DIB(lpbi)) { DWORD dwClrUsed; // 读取dwClrUsed值 dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; if (dwClrUsed != 0) { // 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值 return (WORD)dwClrUsed; } } // 读取象素的位数 if (IS_WIN30_DIB(lpbi)) { // 读取biBitCount值 wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; } else { // 读取biBitCount值 wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; } // 按照象素的位数计算颜色数目 switch (wBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; } } /************************************************************************* * * 函数名称: * DIBBitCount() * * 参数: * LPSTR lpbi - 指向DIB对象的指针 * * 返回值: * WORD - 返回调色板中颜色的种数 * * 说明: * 该函数返回DIBBitCount。 * ************************************************************************/ WORD WINAPI DIBBitCount(LPSTR lpbi) { WORD wBitCount; // 读取象素的位数 if (IS_WIN30_DIB(lpbi)) { // 读取biBitCount值 wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; } else { // 读取biBitCount值 wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; } // 返回wBitCount return wBitCount; } /************************************************************************* * * 函数名称: * CopyHandle() * * 参数: * HGLOBAL h - 要复制的内存区域 * * 返回值: * HGLOBAL - 复制后的新内存区域 * * 说明: * 该函数复制指定的内存区域。返回复制后的新内存区域,出错时返回0。 * ************************************************************************/ HGLOBAL WINAPI CopyHandle (HGLOBAL h) { if (h == NULL) return NULL; // 获取指定内存区域大小 DWORD dwLen = ::GlobalSize((HGLOBAL) h); // 分配新内存空间 HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); // 判断分配是否成功 if (hCopy != NULL) { // 锁定 void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); void* lp = ::GlobalLock((HGLOBAL) h); // 复制 memcpy(lpCopy, lp, dwLen); // 解除锁定 ::GlobalUnlock(hCopy); ::GlobalUnlock(h); } return hCopy; } /************************************************************************* * * 函数名称: * SaveDIB() * * 参数: * HDIB hDib - 要保存的DIB * CFile& file - 保存文件CFile * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE或者CFileException * * 说明: * 该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。 * *************************************************************************/ BOOL WINAPI SaveDIB(HDIB hDib, CFile& file) { // Bitmap文件头 BITMAPFILEHEADER bmfHdr; // 指向BITMAPINFOHEADER的指针 LPBITMAPINFOHEADER lpBI; // DIB大小 DWORD dwDIBSize; if (hDib == NULL) { // 如果DIB为空,返回FALSE return FALSE; } // 读取BITMAPINFO结构,并锁定 lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); if (lpBI == NULL) { // 为空,返回FALSE return FALSE; } // 判断是否是WIN3.0 DIB if (!IS_WIN30_DIB(lpBI)) { // 不支持其它类型的DIB保存 // 解除锁定 ::GlobalUnlock((HGLOBAL) hDib); // 返回FALSE return FALSE; } // 填充文件头 // 文件类型"BM" bmfHdr.bfType = DIB_HEADER_MARKER; // 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并 // 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。 // 文件头大小+颜色表大小 // (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小) dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // 计算图像大小 if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) { // 对于RLE位图,没法计算大小,只能信任biSizeImage内的值 dwDIBSize += lpBI->biSizeImage; } else { // 象素的大小 DWORD dwBmBitsSize; // 大小为Width * Height dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; // 计算出DIB真正的大小 dwDIBSize += dwBmBitsSize; // 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的) lpBI->biSizeImage = dwBmBitsSize; } // 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小 bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); // 两个保留字 bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; // 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小 bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPSTR)lpBI); // 尝试写文件 TRY { // 写文件头 file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 写DIB头和象素 file.WriteHuge(lpBI, dwDIBSize); } CATCH (CFileException, e) { // 解除锁定 ::GlobalUnlock((HGLOBAL) hDib); // 抛出异常 THROW_LAST(); } END_CATCH // 解除锁定 ::GlobalUnlock((HGLOBAL) hDib); // 返回TRUE return TRUE; } /************************************************************************* * * 函数名称: * ReadDIBFile() * * 参数: * CFile& file - 要读取得文件文件CFile * * 返回值: * HDIB - 成功返回DIB的句柄,否则返回NULL。 * * 说明: * 该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER * 外的内容都将被读入内存。 * *************************************************************************/ HDIB WINAPI ReadDIBFile(CFile& file) { BITMAPFILEHEADER bmfHeader; DWORD dwBitsSize; HDIB hDIB; LPSTR pDIB; // 获取DIB(文件)长度(字节) dwBitsSize = file.GetLength(); // 尝试读取DIB文件头 if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) { // 大小不对,返回NULL。 return NULL; } // 判断是否是DIB对象,检查头两个字节是否是"BM" if (bmfHeader.bfType != DIB_HEADER_MARKER) { // 非DIB对象,返回NULL。 return NULL; } // 为DIB分配内存 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); if (hDIB == 0) { // 内存分配失败,返回NULL。 return NULL; } // 锁定 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 读象素 if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != dwBitsSize - sizeof(BITMAPFILEHEADER) ) { // 大小不对。 // 解除锁定 ::GlobalUnlock((HGLOBAL) hDIB); // 释放内存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL。 return NULL; } // 解除锁定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回DIB句柄 return hDIB; } /************************************************************************* * * 函数名称: * CalDistance() * * 参数: * int *data,int *center,int classnum * * 返回值: * double * * 说明: * 该函数用于计算两个象素在N维空间的距离 * *************************************************************************/ double CalDistance(int data[6],int center[6]) { int i,distance[6]; int dsum; dsum=0; double redis; for(i=0;i<6;i++) { distance[i]=data[i]-center[i]; dsum+=distance[i]*distance[i]; } redis=sqrt(dsum*1.0); return redis; } /*************************************************************************** 矩阵求逆函数 功 能: 矩阵求逆 输 入: 矩阵a,阶数n。 输 出: 返回0(成功),1(失败),经求逆后,a矩阵为逆矩阵 *****************************************************************************/ int InverseMatrix(int *a, int n) { int *is,*js; int i,j,k,l,u,v; int temp,max_v; is=(int *)malloc(n*sizeof(int)); js=(int *)malloc(n*sizeof(int)); if(is==NULL||js==NULL) return(0); for(k=0;k<n;k++) { max_v=0; for(i=k;i<n;i++) { for(j=k;j<n;j++) { temp=fabs(a[i*n+j]); if(temp>max_v) { max_v=temp; is[k]=i; js[k]=j; } } } if(max_v==0) { free(is); free(js); return(0); } if(is[k]!=k) { for(j=0;j<n;j++) { u=k*n+j; v=is[k]*n+j; temp=a[u]; a[u]=a[v]; a[v]=temp; } } if(js[k]!=k) { for(i=0;i<n;i++) { u=i*n+k; v=i*n+js[k]; temp=a[u]; a[u]=a[v]; a[v]=temp; } } l=k*n+k; a[l]=1/a[l]; for(j=0;j<n;j++) { if(j!=k) { u=k*n+j; a[u]*=a[l]; } } for(i=0;i<n;i++) { if(i!=k) { for(j=0;j<n;j++) { if(j!=k) { u=i*n+j; a[u]-=a[i*n+k]*a[k*n+j]; } } } } for(i=0;i<n;i++) { if(i!=k) { u=i*n+k; a[u]*=-a[l]; } } } for(k=n-1;k>=0;k--) { if(js[k]!=k) { for(j=0;j<n;j++) { u=k*n+j; v=js[k]*n+j; temp=a[u]; a[u]=a[v]; a[v]=temp; } } if(is[k]!=k) { for(i=0;i<n;i++) { u=i*n+k; v=i*n+is[k]; temp=a[u]; a[u]=a[v]; a[v]=temp; } } } free(is); free(js); return(1); } /*************************************************************************** //功 能: 矩阵转置 //输 入: 矩阵a(mxn阶)转置后存在矩阵at(nxm阶)中 //输 出: void,结果在矩阵at中 *****************************************************************************/ void TransposeMatrix(int *a, int *at, int m, int n) { int i,j; for(i=0;i<n;i++) for(j=0;j<m;j++) *(at+i*m+j)=*(a+j*n+i); } /*************************************************************************** //功 能: 矩阵相乘 //输 入: 矩阵a(mxn阶)乘以矩阵b(nxk阶)等于矩阵c(mxk阶)。 //输 出: void,结果在矩阵c中 *****************************************************************************/ void MultiplyMatrix(int *a, int *b, int *c, int m, int n, int k) { int i,j,ii; for(i=0;i<m;i++) { for(j=0;j<k;j++) { *(c+i*k+j)=0; for(ii=0;ii<n;ii++) *(c+i*k+j)=*(c+i*k+j)+*(a+i*n+ii)**(b+ii*k+j); } } } /************************************************************************* * * 函数名称: * MedianFilter() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * int iFilterH - 滤波器的高度 * int iFilterW - 滤波器的宽度 * int iFilterMX - 滤波器的中心元素X坐标 * int iFilterMY - 滤波器的中心元素Y坐标 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数对DIB图像进行中值滤波。 * ************************************************************************/ double MedianFilter(CString m_band, LONG lWidth, LONG lHeight, int iFilterH, int iFilterW, int iFilterMX, int iFilterMY) { CFile file_raw; CFileException fe; HDIB m_hDIB; long lLineBytes; lLineBytes = WIDTHBYTES(lWidth*8); file_raw.Open(m_band, Cfile::modeReadWrite | Cfile::shareDenyNone|CFil e::typeBinary, &fe); DWORD dwBitsSize = lLineBytes*lHeight; //分配空间 m_hDIB=(HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize) ; //dDIB的内存地址 LPSTR lpDIBBits = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); file_raw.Read(lpDIBBits,lLineBytes*lHeight); // 指向源图像的指针 unsigned char* lpSrc; // 指向要复制区域的指针 unsigned char* lpDst; // 指向复制图像的指针 LPSTR lpNewDIBBits; HLOCAL hNewDIBBits; // 指向滤波器数组的指针 unsigned char * aValue; HLOCAL hArray; // 循环变量 LONG i; LONG j; LONG k; LONG l; // 图像每行的字节数 // LONG lLineBytes; // 计算图像每行的字节数 // lLineBytes = WIDTHBYTES(lWidth * 8); // 暂时分配内存,以保存新图像 hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); // 判断是否内存分配失败 if (hNewDIBBits == NULL) { // 分配内存失败 return FALSE; } // 锁定内存 lpNewDIBBits = (char * )LocalLock(hNewDIBBits); // 初始化图像为原始图像 memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight); // 暂时分配内存,以保存滤波器数组 hArray = LocalAlloc(LHND, iFilterH * iFilterW); // 判断是否内存分配失败 // if (hArray == NULL) // { // 释放内存 // LocalUnlock(hNewDIBBits); // LocalFree(hNewDIBBits); // 分配内存失败 // return FALSE; // } // 锁定内存 aValue = (unsigned char * )LocalLock(hArray); // 开始中值滤波 // 行(除去边缘几行) for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++) { // 列(除去边缘几列) for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++) { // 指向新DIB第i行,第j个象素的指针 lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j; // 读取滤波器数组 for (k = 0; k < iFilterH; k++) { for (l = 0; l < iFilterW; l++) { // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素 的指针 lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l; // 保存象素值 aValue[k * iFilterW + l] = *lpSrc; } } // 获取中值 * lpDst = GetMedianNum(aValue, iFilterH * iFilterW); } } // 复制变换后的图像 // memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); double entropy = 0.0; int *array; array = new int[256]; for(i=0;i<256;i++) *(array+i)=0; long total; total = lWidth*lHeight; //统计图象中各灰度级出现的次数 for(i=0;i<lHeight;i++) for(j=0;j<lWidth;j++) { unsigned char* lpdst; lpdst = (unsigned char*)lpNewDIBBits + lLineBytes*i + j; array[*lpdst]++; } for(i=0;i<256;i++) { double tem=0.0; tem = array[i]*1.0/total; if(tem != 0) entropy += (-1)*tem*log(tem*1.0); else continue; } delete array; // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); LocalUnlock(hArray); LocalFree(hArray); return entropy; // 返回 // return TRUE; } /************************************************************************* * * 函数名称: * GetMedianNum() * * 参数: * unsigned char * bpArray - 指向要获取中值的数组指针 * int iFilterLen - 数组长度 * * 返回值: * unsigned char - 返回指定数组的中值。 * * 说明: * 该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。 * ************************************************************************/ unsigned char WINAPI GetMedianNum(unsigned char * bArray, int iFilterLen) { // 循环变量 int i; int j; // 中间变量 unsigned char bTemp; // 用冒泡法对数组进行排序 for (j = 0; j < iFilterLen - 1; j ++) { for (i = 0; i < iFilterLen - j - 1; i ++) { if (bArray[i] > bArray[i + 1]) { // 互换 bTemp = bArray[i]; bArray[i] = bArray[i + 1]; bArray[i + 1] = bTemp; } } } // 计算中值 if ((iFilterLen & 1) > 0) { // 数组有奇数个元素,返回中间一个元素 bTemp = bArray[(iFilterLen + 1) / 2]; } else { // 数组有偶数个元素,返回中间两个元素平均值 bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2; } // 返回中值 return bTemp; } /************************************************************************* * * 函数名称: * CalEntropy() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * * 返回值: * double - 返回指定数组的中值。 * ************************************************************************/ double CalEntropy(LPSTR lpDIBBits,LONG lWidth,LONG lHeight) { int i,j; double entropy = 0.0; int *array; array = new int[256]; memset(array,0,256); long total; total = lWidth*lHeight; long lLineBytes; lLineBytes = WIDTHBYTES(lWidth*8); //统计图象中各灰度级出现的次数 for(i=0;i<lHeight;i++) for(j=0;j<lWidth;j++) { unsigned char* lpdst; lpdst = (unsigned char*)lpDIBBits + lLineBytes*i + j; array[*lpdst]++; } for(i=0;i<256;i++) { double tem=0.0; tem = array[i]*1.0/total; if(tem != 0) entropy += (-1)*tem*log(tem*1.0); else continue; } delete array; return entropy; } /***********************************************************/ /***********************************************************/ double CalEntropyAndReadRAW(CString m_band,int width,int height) { //读RAW格式文件 CFile file_raw; CFileException fe; HDIB m_hDIB; long lLineBytes; lLineBytes = WIDTHBYTES(width*8); file_raw.Open(m_band, Cfile::modeReadWrite | Cfile::shareDenyNone|CFil e::typeBinary, &fe); DWORD dwBitsSize = lLineBytes*height; //分配空间 m_hDIB=(HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize) ; //dDIB的内存地址 LPSTR pDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); file_raw.Read(pDIB,lLineBytes*height); int i,j; double entropy = 0.0; int *array; array = new int[256]; for(i=0;i<256;i++) *(array+i)=0; long total; total = width*height; //统计图象中各灰度级出现的次数 for(i=0;i<height;i++) for(j=0;j<width;j++) { unsigned char* lpdst; lpdst = (unsigned char*)pDIB + lLineBytes*i + j; array[*lpdst]++; } for(i=0;i<256;i++) { double tem=0.0; tem = array[i]*1.0/total; if(tem != 0) entropy += (-1)*tem*log(tem*1.0); else continue; } // entropy = CalEntropy(pDIB,width,height); return entropy; } -- ※ 来源:·珞珈山水BBS站 http://bbs.whu.edu.cn·[FROM: 219.140.158.*] |
| [返回单文区目录] |
|
|