📄 dibview.cpp
字号:
// dibview.cpp : implementation of the CDibView class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include "diblook.h"
#include "dibdoc.h"
#include "dibview.h"
#include "dibapi.h"
#include "mainfrm.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
enum SPEED {
SLOW,
MIDFAST,
FAST
};
#define IMAGE_MAX 2000
#define HOR 361
#define VERTI 362
HDIB WINAPI Rotate(HDIB m_hDIB,int offset,SPEED speed)
// m_hDIB 要处理的图像句柄
// offset 0到359之间的整数及HOR,VERTI, HOR表示水平翻转, VERTI表示垂直翻转。
//对0,90, 180, 270度旋转算法特殊处理以提高速度。
//speed 为FAST则不用插值算法, 直接用式(6.2)求解, 速度快。
//speed 为MIDFAST则用双线性插值法。
//speed为SLOW保留
{
BYTE * image[IMAGE_MAX];
BYTE * newimage[IMAGE_MAX];
double ks,yt,af,bt;
int xm[4],yn[4];
int x,y;
int tmpx,tmpy;
LPSTR lp=(LPSTR)::GlobalLock(m_hDIB);
LPBITMAPINFOHEADER lh=(LPBITMAPINFOHEADER)lp;
int biWidth;
lp=lp+1024+40;
if(lh->biBitCount!=8)
{
AfxMessageBox("not 8 bit bmp");
return NULL;
}
biWidth=lh->biWidth;
if(biWidth%4!=0)
biWidth+=(4-biWidth%4);
int biHeight=lh->biHeight;
float sinq,cosq,sinqcosq,sinqsinq;
float pi=(float)3.1415927;
int i,j;
for(i=0;i<biHeight;i++)
image[i]=(BYTE *)(lp+(biHeight-i-1)*biWidth);
//将 m_hDIB转换为image数学组
int newWidth;
int newHeight;
LPSTR lpnew;
LPSTR lptmp=lp-1024-40;
LPBITMAPINFOHEADER lhtmp;
HDIB newhDIB;
switch(offset)
{
case 90: //旋转90°,特殊处理,速度快
newHeight=lh->biWidth;
newWidth=lh->biHeight;
if(newWidth%4!=0)
newWidth+=(4-newWidth%4);
newhDIB = (HDIB)
::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,40+1024+newWidth*newHeight );
lpnew=(LPSTR)::GlobalLock(newhDIB);
//为旋转后的图像分配内存
lptmp=(LPSTR)lh;
for(i=0;i<40+1024;i++)
*(lpnew+i)=lptmp[i];
//复制bmp文件头
lhtmp=(LPBITMAPINFOHEADER)lpnew;
lhtmp->biWidth=lh->biHeight;
lhtmp->biHeight=lh->biWidth;
lhtmp->biSizeImage=0;
//图像宽高互换
for(i=0;i<newHeight;i++)
newimage[i]=(BYTE *)(lpnew+40+(newHeight-i-1)*newWidth+1024);
for(i=0;i<newHeight;i++)
for(j=0;j<lh->biHeight;j++)
{
newimage[i][j]=image[j][(newHeight-i-1)];
}//为新图像赋值
break;
case 0://旋转0度, 等价于复制图像
newHeight=lh->biHeight;
newWidth=lh->biWidth;
if(newWidth%4!=0)
newWidth+=(4-newWidth%4);
newhDIB = (HDIB)
::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,40+1024+newWidth*newHeight );
lpnew=(LPSTR)::GlobalLock(newhDIB);
//为旋转后的图像分配内存
lptmp=(LPSTR)lh;
for(i=0;i<40+1024;i++)
*(lpnew+i)=lptmp[i];
//复制bmp文件头
lhtmp=(LPBITMAPINFOHEADER)lpnew;
lhtmp->biWidth=lh->biWidth;
lhtmp->biHeight=lh->biHeight;
lhtmp->biSizeImage=0;
//图像宽高互换
for(i=0;i<newHeight;i++)
newimage[i]=(BYTE *)(lpnew+40+(newHeight-i-1)*newWidth+1024);
for(i=0;i<newHeight;i++)
for(j=0;j<lh->biHeight;j++)
{
newimage[i][j]=image[i][j];
}//为新图像赋值
break;
case HOR: //水平翻转
newHeight=lh->biHeight;
newWidth=lh->biWidth;
if(newWidth%4!=0)
newWidth+=(4-newWidth%4);
newhDIB = (HDIB)
::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,40+1024+newWidth*newHeight );
lpnew=(LPSTR)::GlobalLock(newhDIB);
//为新图像分配内存
lptmp=(LPSTR)lh;
for(i=0;i<40+1024;i++)
*(lpnew+i)=lptmp[i];
lhtmp=(LPBITMAPINFOHEADER)lpnew;
lhtmp->biWidth=lh->biWidth;
lhtmp->biHeight=lh->biHeight;
lhtmp->biSizeImage=0;
//为新的bmp信息头赋值
for(i=0;i<newHeight;i++)
newimage[i]=(BYTE *)(lpnew+40+1024+(newHeight-i-1)*newWidth);
for(i=0;i<newHeight;i++)
for(j=0;j<lh->biWidth;j++)
{
newimage[i][j]=image[i][(lh->biWidth-j-1)];
} //翻转复制图像
break;
case 180: //180 度特殊处理速度快
newHeight=lh->biHeight;
newWidth=lh->biWidth;
if(newWidth%4!=0)
newWidth+=(4-newWidth%4);
newhDIB = (HDIB)
::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,40+1024+newWidth*newHeight );
lpnew=(LPSTR)::GlobalLock(newhDIB);
//分配图像
lptmp=(LPSTR)lh;
for(i=0;i<40+1024;i++)
*(lpnew+i)=lptmp[i];
lhtmp=(LPBITMAPINFOHEADER)lpnew;
lhtmp->biWidth=lh->biWidth;
lhtmp->biHeight=lh->biHeight;
lhtmp->biSizeImage=0;
for(i=0;i<newHeight;i++)
newimage[i]=(BYTE *)(lpnew+40+1024+(newHeight-i-1)*newWidth);
for(i=0;i<newHeight;i++)
for(j=0;j<lh->biWidth;j++)
{
newimage[i][j]=image[newHeight-1-i][lh->biWidth-j-1];
} //按照旋转180度复制图像
break;
break;
case VERTI: //垂直翻转
newHeight=lh->biHeight;
newWidth=lh->biWidth;
if(newWidth%4!=0)
newWidth+=(4-newWidth%4);
newhDIB = (HDIB)
::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,1064+newWidth*newHeight);
lpnew=(LPSTR)::GlobalLock(newhDIB);
//分配内存
lptmp=(LPSTR)lh;
for(i=0;i<1064;i++)
*(lpnew+i)=lptmp[i];
lhtmp=(LPBITMAPINFOHEADER)lpnew;
lhtmp->biWidth=lh->biWidth;
lhtmp->biHeight=lh->biHeight;
lhtmp->biSizeImage=0;
//复制信息头
for(i=0;i<newHeight;i++)
newimage[i]=(BYTE *)(lpnew+1064+(newHeight-i-1)*newWidth);
for(i=0;i<newHeight;i++)
for(j=0;j<lh->biWidth;j++)
{
newimage[i][j]=image[newHeight-1-i][j];
}//按垂直翻转复制
break;
case 270:
newHeight=lh->biWidth;
newWidth=lh->biHeight;
if(newWidth%4!=0)
newWidth+=(4-newWidth%4);
newhDIB = (HDIB)
::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,1064+newWidth*newHeight );
lpnew=(LPSTR)::GlobalLock(newhDIB);
//分配内存
lptmp=(LPSTR)lh;
for(i=0;i<1064;i++)
*(lpnew+i)=lptmp[i];
lhtmp=(LPBITMAPINFOHEADER)lpnew;
lhtmp->biWidth=lh->biHeight;
lhtmp->biHeight=lh->biWidth;
lhtmp->biSizeImage=0;
//复制信息头
for(i=0;i<newHeight;i++)
newimage[i]=(BYTE *)(lpnew+1064+(newHeight-i-1)*newWidth);
for(i=0;i<newHeight;i++)
for(j=0;j<lh->biHeight;j++)
{
newimage[i][j]=image[lh->biHeight-1-j][i];
//复制图像
}
break;
default: //旋转任意角度
sinq=(float)sin(offset*1.0/180*pi);
cosq=(float)cos(offset*1.0/180*pi);
sinqcosq=(float)(sinq*cosq);
sinqsinq=(float)(sinq*sinq);
newHeight=(int)((lh->biWidth*sinq+lh->biHeight*cosq)+0.5);
newWidth=((int)(lh->biHeight*sinq+lh->biWidth*cosq+0.5));
//新图像宽度和高度
newHeight=abs(newHeight);
newWidth=abs(newWidth);
if(newWidth%4!=0)
newWidth+=(4-newWidth%4);
newhDIB = (HDIB)
::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,1064+newWidth*newHeight );
lpnew=(LPSTR)::GlobalLock(newhDIB);
lptmp=(LPSTR)lh;
for(i=0;i<1064;i++)
*(lpnew+i)=lptmp[i];
lhtmp=(LPBITMAPINFOHEADER)lpnew;
lhtmp->biWidth=abs(newWidth);
lhtmp->biHeight=abs(newHeight);
lhtmp->biSizeImage=0;
//复制信息头
for(i=0;i<newHeight;i++)
newimage[i]=(BYTE *)(lpnew+1064+(newHeight-i-1)*newWidth);
for(i=0;i<newHeight;i++)
for(j=0;j<lhtmp->biWidth;j++)
{
ks=j*cosq-i*sinq+lh->biWidth*sinqsinq;
yt=j*sinq+i*cosq-lh->biWidth*sinqcosq;
switch(speed)
{
case FAST:
tmpx=(int)(ks+0.5);
tmpy=(int)(yt+0.5);
if(tmpx<0||tmpx>=lh->biWidth||tmpy<0||tmpy>=lh->biHeight)
{
continue;
}
newimage[i][j]=image[tmpy][tmpx];
break;
case MIDFAST:
tmpx=(int)ks;
tmpy=(int)yt;
af=ks-tmpx;
bt=yt-tmpy;
if(tmpx<0||tmpx>=lh->biWidth||tmpy<0||tmpy>=lh->biHeight)
{
continue;
}
if(tmpx==lh->biWidth-1||tmpy==lh->biHeight-1)
{
newimage[i][j]=image[tmpy][tmpx];
continue;
}
newimage[i][j]=(BYTE)(image[tmpy][tmpx]*(1-af)*(1-bt)+
image[tmpy][(tmpx+1)]*(af)*(1-bt)+
image[tmpy+1][tmpx]*(1-af)*bt+
image[tmpy+1][(tmpx+1)]*(af)*bt+0.5)
;
//复制图像
break;
}
}
break;
break;
}
::GlobalLock(m_hDIB);
::GlobalLock(newhDIB);
return newhDIB;
}
/////////////////////////////////////////////////////////////////////////////
// CDibView
#define houghthresh 10
void Welcom();
void InitImage(BYTE *image[2000], int w, int h);
void ReadRawFile(BYTE *image[2000], int w, int h, char filepath[200]);
void SaveRawFile(BYTE *image[2000], int w, int h, char filepath[200]);
void WINAPI GetImage(HDIB hDIB, BYTE *image[]);
void WINAPI GetImage(HDIB hDIB, BYTE *image[])
{
LPSTR lp=(LPSTR)::GlobalLock(hDIB);
LPBITMAPINFOHEADER lh=
(LPBITMAPINFOHEADER)lp;
int biWidth=DIBWidth(lp);
int biHeight=DIBHeight(lp);
if (biWidth%4!=0) biWidth+=(4-biWidth%4);
lp=FindDIBBits(lp);
if(lh->biBitCount==8)
for(int i=0;i<biHeight;i++)
image[i]=(BYTE *)(lp+(biHeight-1-i)*biWidth);
else
{
AfxMessageBox("Not 8 bit bitmap!");
}
::GlobalUnlock(hDIB);
}
void Welcom()
{
printf("\n");
printf("********\n");
printf("Welcome!\n");
printf("********\n");
printf("\n");
}
void InitImage(BYTE *image[2000], int w, int h)
{
for(int i=0;i<h;i++)
image[i]=(BYTE *)new BYTE[w];
for(i=0;i<h;i++)
for(int j=0;j<w;j++)
image[i][j]=0;
}
void ReadRawFile(BYTE *image[2000], int w, int h, char filepath[200])
{
FILE *fp=fopen(filepath,"rb");
if(fp==NULL) {printf("error open \"%s\" !\n",filepath);exit(0);}
for(int i=0;i<h;i++)
fread(image[i],1,w,fp);
fclose(fp);
printf("success open \"%s\" !\n",filepath);
}
void SaveRawFile(BYTE *image[2000], int w, int h, char filepath[200])
{
FILE *fp=fopen(filepath,"wb");
if(fp==NULL) {printf("error open \"%s\" to write !\n",filepath);exit(0);}
for(int i=0;i<h;i++)
fwrite(image[i],1,w,fp);
fclose(fp);
printf("success open \"%s\" to write !\n",filepath);
}
void diedaiyz(BYTE *image[2000],int w,int h);
void sanfenyz(BYTE *image[2000],int w,int h);
void sobel(BYTE *image_in[2000],int w,int h,BYTE *image_out[2000]);
void lapla1(BYTE *image_in[2000],int w,int h,BYTE *image_out[2000]);
void lapla2(BYTE *image_in[2000],int w,int h,BYTE *image_out[2000]);
void zzlb(BYTE *image_in[2000],int w,int h,BYTE *image_out[2000]);
void houghtrans1(BYTE *image_in[2000],int w,int h);
void houghtrans2(BYTE *image_in[2000],int w,int h);
void makeline1(BYTE *image_in[2000],int w,int h,double t,int k,int r,BYTE *image_out[2000]);
void makeline2(BYTE *image_in[2000],int w,int h,double t,int k,int r,BYTE *image_out[2000]);
int medianvalue(int *value);
int main()
{
int w=512,h=512;
Welcom();
BYTE *image[2000];
InitImage(image,w,h);
ReadRawFile(image,w,h,"D:\\peacock.raw");
//图像读取的路径为:D:\\peacock.raw ,在保存的时候存在了E盘
//且均以peacock_后缀.raw命名,例如:peacock_lapla2.raw,peacock_hough.raw
//我们将所有的函数按不同的顺序进行组合,以期得到最好的边缘提取效果
// diedaiyz(image,w,h); //迭代法选取阈值,二值化,并将二值化后的图像保存
// sanfenyz(image,w,h); //T=max-(max-min)/3,二值化,并将二值化后的图像保存
// BYTE *image2[2000];
// InitImage(image2,w,h);
// zzlb(image,w,h,image2); //中值滤波,并将滤波后的图像保存
//前面的为输入数组,如image;后面的为输出数组,如image2。以下均同,请注意之!
BYTE *image1[2000];
InitImage(image1,w,h);
// sobel(image,w,h,image1); //sobel算子对图像进行梯度锐化,并将梯度锐化后的图像保存
// lapla1(image,w,h,image1); //拉普拉斯算子,模板一:{0,-1,0,-1,4,-1,0,-1,0},并将梯度锐化后的图像保存
lapla2(image,w,h,image1); //拉普拉斯算子,模板二:{-1,-1,-1,-1,8,-1, -1,-1,-1},并将梯度锐化后的图像保存
// BYTE *image2[2000];
// InitImage(image2,w,h);
// zzlb(image1,w,h,image2); //中值滤波
// diedaiyz(image1,w,h); //迭代法选取阈值,二值化
sanfenyz(image1,w,h); //T=max-(max-min)/3,二值化
// BYTE *image2[2000];
// InitImage(image2,w,h);
// zzlb(image1,w,h,image2); //中值滤波
// houghtrans1(image1,w,h); //hough变换第一种算法:5x5模板
houghtrans2(image1,w,h); //hough变换第二种算法:循环hough,多次提取最长直线
return 1;
}
void houghtrans1(BYTE *image_in[2000],int w,int h) //hough变换第一种算法
{
double t=3.1415926;
t=t/180;
int rmax=w+h+1;
int *hough[180];
int k,r;
for(k=0;k<180;k++)
hough[k]=(int *)new int[rmax];
for(k=0;k<180;k++)
for(r=0;r<rmax;r++)
hough[k][r]=0;
int i,j;
for(i=0;i<h;i++) //将大于0的点标记为255,即白点
//自己绘制的图像中可能存在一些点既不是0也不是255,另外为了避免由于前期处理不当导致hough失败
for(j=0;j<w;j++)
{if(image_in[i][j]>0)image_in[i][j]=255;}
for(i=0;i<h;i++) //对原图中的白点做hough变换
for(j=0;j<w;j++)
{
if(image_in[i][j]==255)
{
for(k=0;k<180;k++)
{
r=(int)(j*cos(k*t)+i*sin(k*t));
if(r<0)r+=w+h+1;
hough[k][r]++;
}
}
}
BYTE *image_out[2000];
InitImage(image_out,w,h);
for(k=0;k<180;k++) //寻找数组hough[][]的各个峰值,采用5x5模板算法
for(r=0;r<rmax;r++)
{
if(hough[k][r]>houghthresh)
{
int tag=1;
int dk,dr,dkt,drt;
for(dk=k-2;dk<=k+2;dk++)
{
for(dr=r-2;dr<=r+2;dr++)
{
if(dk<0)dkt=dk+180;
else if(dk>=180)dkt=dk-180;
else dkt=dk;
if(dr<0)drt=dr+w+h+1;
else drt=dr;
if(drt<rmax&&hough[dkt][drt]>hough[k][r])
{tag=0;break;}
}
if(tag==0)break;
}
if(tag==1)
{
// makeline1(image_in,w,h,t,k,r,image_out); //寻找到一条直线立即绘制
makeline2(image_in,w,h,t,k,r,image_out);
}
}
}
SaveRawFile(image_out,w,h,"E:\\peacock_hough.raw");
}
void houghtrans2(BYTE *image_in[2000],int w,int h) //hough变换第二种算法
{
BYTE *image_out[2000];
InitImage(image_out,w,h);
double t=3.1415926;
t=t/180;
int rmax=w+h+1;
int *hough[180];
int k,r;
for(k=0;k<180;k++)
hough[k]=(int *)new int[rmax];
int i,j;
for(i=0;i<h;i++)
for(j=0;j<w;j++)
if(image_in[i][j]>0)image_in[i][j]=255;//此处以上与算法一相同
while(1) //对hough变换的全部过程做循环
{
for(k=0;k<180;k++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -