画直方图,自动色阶
来源:互联网 发布:提高记忆力的方法知乎 编辑:程序博客网 时间:2024/06/06 17:10
基于mfc对话框,在对话框上插入两个图像控件,图像控件一显示原图,图像控件二,显示灰度图,或者轮廓图,或者自动色阶调整后的图片。并且在对话框上载入原图后,画出原图的像素中R值的直方图,图像控件二上显示灰度图时,画出灰度直方图,图像控件二上显示经过自动色阶处理过的图像后,显示其自动色阶的直方图
色阶算法参考网址 :http://www.cnblogs.com/laviewpbt/archive/2009/05/31/1492431.html
画直方图,参考网址http://blog.csdn.net/ch_jinyi/article/details/7487217
1.首先新建一个基于mfc对话框的工程名为 histogram,在对话框上加入两个图像控件IDC_SHOW和IDC_OUTLINE,IDC_SHOW控件用来显示原图,IDC_OUTLINE控件上用来显示处理过的图像。首先载入原图,这个在前面已经做个笔记(方法同上),这里不做讲解。代码如下:
void ChistogDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
BYTE *pData=NULL;
unsigned char gray;
CFileDialog cfd(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_T("text(*.text)|*.text|图片文件(*.jpg;*.jpeg;*.gif;*.bmp)|*.jpg;*.jpeg;*.gif;*.bmp|位图文件(*.BMP)|*.BMP||"));
if(cfd.DoModal()!=IDOK) //判断是否获得图片
{
return;
}
image.Destroy();
m_path = cfd.GetPathName(); //获得图片路径
image.Load(m_path); //装载路径下图片信息到图片类
ShowPicture();
Showhistogram();
}
载入图像后需要画出原图图像r值的直方图,在打开对话框选择图像的时候,调用函数Showhistogram();在这里调用保证图片显示的图示,原图的直方图也同一时间显示。函数如下:
struct IAMGE_PIXEL{
unsigned char b;
unsigned char g;
unsigned char r;
};
void ChistogDlg::Showhistogram(void)
{
CImage image2;
BYTE *pData=NULL;
BYTE *pData1=NULL;
unsigned char gray;
image2.Create( image.GetWidth(),image.GetHeight(),image.GetBPP(),0);//创建一张新图形
//GetBPP()是图像的位深,灰度图位深为8
if(image.GetPitch()<0)
{ //GetPitch() 图像的间距。 如果返回值为负,位图是一个从下到上 DIB,并且原点是左下角。 如果 //返回值为正的,位图是一组 DIB,并且原点为左上角
pData= (BYTE*)image.GetBits()+(image.GetPitch()*(image.GetHeight()-1));
//GetPitch()的负数话,图像原点为坐下角,通过图像间距*图像的高度-1左下角的地址
//将图像地址偏移到左上角
}
else
{
pData = (BYTE*)image.GetBits(); //为正数,图像原始位置地址不变
}
if(image2.GetPitch()<0)
{
pData1 = (BYTE*)image2.GetBits()+(image2.GetPitch()*(image2.GetHeight()-1));
}
else
{
pData1 = (BYTE*)image2.GetBits();
}
//申请一块内存,用来保存图像的数据,宽*高等于图像的总像素,但是要对每个像素的r值进行处理,
//定义了IAMGE_PIXEL结构体,用来读取每个像素的r,g,b值,申请的大小在总像素上再*3
IAMGE_PIXEL **pixelData2= (IAMGE_PIXEL**) malloc(image.GetWidth() * image.GetHeight() * 3 );
IAMGE_PIXEL **pixelData1= (IAMGE_PIXEL**) malloc(image.GetWidth() * image.GetHeight() * 3 );
for (int i=0; i<image.GetHeight(); i++)
{ //将image图像的每一行的数据,保存在pixelData2这个二维数组里面,后面通过行指针,能
//访问具体的某行某列的
pixelData2[i] =(IAMGE_PIXEL *) ( pData+ image.GetWidth()*i*3);
pixelData1[i] =(IAMGE_PIXEL *) ( pData1+ image2.GetWidth()*i*3);
//将image2的行地址保存在 pixelData1中,后续可对具体某行某列的元素做操作
}
for(int i=0; i<image.GetHeight();i++)
{
for( int j=0; j<image.GetWidth(); j++)
{
unsigned char m;
pixelData1[i][j].r= pixelData2[i][j].r;
//因为只画r值的直方图,所以只需把pixelData2二维数组中r的值,赋值给
// pixelData1。此时pixelData1中每个像素的r值有值,其他值为空
m=pixelData1[i][j].r;
//将每个色阶的r值的像素点的个数做统计,保存在数组 picture_r中
picture_r[m]++;
}
}
free(pixelData2);
free(pixelData1);
CClientDC dc(this);
CRect rect_ctr;
CRect m_rect(27,290,283,488); //画一个固定的矩形
const int x0=27,y0=290,x1=283,y1=488;
dc. FillSolidRect(& m_rect,RGB(255,255,255)); //白色填充上面的矩形
const int N = 256;
int dx = (x1-x0)/N;//数据的个数及条图的宽度,直方图的x轴坐标,即对应256个色阶
t_max=picture_r[0];
for(int r=1;r<256;r++)
{
if(t_max<picture_r[r]) //找出256个色阶中,占最多像素的色阶
t_max=picture_r[r];
}
int a=t_max;
CBrush br;
int i,x;
for (i = 0,x=x0;i<N;++i,x+=dx)
{
br.CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0)); //在固定的矩形中画黑色的矩形
dc.SelectObject(&br);
dc.Rectangle(x,488-(float(picture_r[i]/t_max*198)),x+dx,488);
//x坐标的起点为白色矩形的left坐标,每画一个矩形x坐标加1,纵坐标为每个色阶所占像素点
//的个数,是在固定的白色矩形里面画矩形,固定矩形的大小宽为256即对应的色阶,,长为198,每个色阶
//所占像素的大小最多可以占图像宽*高的个数,如果按照一定的比例把每个色阶所占的像素的总数画在
//白色的矩形里面,则picture_r[i]/总像素*198.应总像素比较大,(除以总像素画出来的直方图效果不
//明显,)所以找到所有色阶的一个最大值,让这个色阶高度填满整个矩形,其他色阶按这个比例依次填
//充,画矩形参数需要int类型,所以上面有求比例的时候,将其转换为float类型
float j=(float(picture_r[i]/t_max));
dc.SelectStockObject(WHITE_BRUSH);
br.DeleteObject();
}
for (int i=0;i<256;i++)
{
picture_r[i]=0; //这个变量定义为全局变量,最后要清零,必须程序没有退出,只是
//不停的载入图片,这个全局变量的值不清掉,会导致画直方图的时候,数据有误,定义全局
//变量后一定要清楚全局变量的值
}
}
2.在dlg对话框中,插入button按键,caption改为outline,按键里面添加函数如下,主要是得到一张图片的轮廓。
void ChistogDlg::OnBnClickedLine()
{
// TODO: 在此添加控件通知处理程序代码
CImage image1;
BYTE *pData1=NULL;
BYTE *pData2=NULL;
int value1;
int value2;
int value3;
int value4;
int value5;
unsigned char n;
image1.Create( image.GetWidth(),image.GetHeight(),image.GetBPP(),0);
if(image1.GetPitch()<0)
{
pData1 = (BYTE*)image1.GetBits()+(image1.GetPitch()*(image1.GetHeight()-1));
}
else
{
pData1 = (BYTE*)image1.GetBits();
}
if(image.GetPitch()<0)
{
pData2 = (BYTE*)image.GetBits()+(image.GetPitch()*(image.GetHeight()-1));
}
else
{
pData2 = (BYTE*)image.GetBits();
}
IAMGE_PIXEL **pixelData2= (IAMGE_PIXEL**) malloc(image.GetWidth() * image.GetHeight() * 3 );
IAMGE_PIXEL **pixelData1= (IAMGE_PIXEL**) malloc(image.GetWidth() * image.GetHeight() * 3 );
for (int i=0; i<image.GetHeight(); i++)
{
pixelData1[i] =(IAMGE_PIXEL *) ( pData1+ image.GetWidth()*i*3);
pixelData2[i] =(IAMGE_PIXEL *) ( pData2+ image.GetWidth()*i*3);
}
for(int i=1; i<image.GetHeight()-1;i++)
{
for( int j=1; j<image.GetWidth()-1; j++)
{ pixelData1[i][j].b=pixelData2[i][j].b;
pixelData1[i][j].r=pixelData2[i][j].r;
value1=abs(pixelData2[i-1][j].g+pixelData2[i-1][j-1].g+pixelData2[i-1][j+1].g- pixelData2[i+1][j].g-pixelData2[i+1][j-1].g-pixelData2[i+1][j+1].g);
value2= abs(pixelData2[i-1][j-1].g+pixelData2[i][j-1].g+pixelData2[i+1][j-1].g-pixelData2[i-1][j+1].g-pixelData2[i][j+1].g-pixelData2[i+1][j+1].g);
value3= abs(pixelData2[i-1][j-1].g+pixelData2[i-1][j].g+pixelData2[i][j-1].g-pixelData2[i][j+1].g-pixelData2[i+1][j].g-pixelData2[i+1][j+1].g);
value4= abs(pixelData2[i][j-1].g+pixelData2[i+1][j-1].g+pixelData2[i+1][j].g-pixelData2[i-1][j].g-pixelData2[i-1][j+1].g-pixelData2[i][j+1].g);
value5 = max(max(max(value1,value2),value3),value4);
if(value5>60)
{
pixelData1[i][j].g=255;
pixelData1[i][j].r=255;
pixelData1[i][j].b=255;
}
else
{
pixelData1[i][j].g=pixelData2[i][j].g;
pixelData1[i][j].r=pixelData2[i][j].r;
pixelData1[i][j].b=pixelData2[i][j].b;
}
}
}
CRect rect;
m_outline.GetClientRect(&rect); //m_picture为Picture Control控件变量,获得控件的区域对象
CDC * pDC=GetDlgItem(IDC_OUTLINE)->GetDC();
pDC->SetStretchBltMode(STRETCH_HALFTONE);
image1.Draw( pDC -> m_hDC,rect); //图片类的图片绘制Draw函数
ReleaseDC(pDC);
free(pixelData1);
free(pixelData2);
}
3.在dlg对话框中,插入button按键,caption改为gray,其代码如下:
void ChistogDlg::OnBnClickedGray()
{
// TODO: 在此添加控件通知处理程序代码
BYTE *pData1=NULL;
BYTE *pData2=NULL;
unsigned char n;
CImage image2;
RGBQUAD colortable[256]; //定义色盘的结构体
image2.Create(image.GetWidth(),image.GetHeight(),8,0); //创建8位图像位深度的图片,保存
//灰度图片
if(image.GetPitch()<0)
pData1=(BYTE*)image.GetBits()+(image.GetPitch()*(image.GetHeight()-1));
else
pData1=(BYTE*)image.GetBits();
if(image2.GetPitch()<0)
pData2=(BYTE*)image2.GetBits()+(image2.GetPitch()*(image2.GetHeight()-1));
else
pData2=(BYTE*)image2.GetBits();
IAMGE_PIXEL **pixelData= (IAMGE_PIXEL**) malloc(image2.GetWidth() *image2.GetHeight() * 3);
char **pixelDatatemp1= (char **) malloc(image2.GetWidth() *image2.GetHeight() );
memset(pixelDatatemp1,0,image2.GetWidth() *image2.GetHeight() );
for (int i=0; i<image2.GetHeight(); i++)
{
pixelData[i] =(IAMGE_PIXEL *) (pData1 + image.GetWidth()*i*3);
pixelDatatemp1[i]=(char *) ( pData2+image2.GetWidth()*i);
}
for(int i=0; i<image2.GetHeight();i++)
{
for( int j=0; j<image2.GetWidth();j++)
{
n=0.59*pixelData[i][j].g+0.3*pixelData[i][j].r+0.11*pixelData[i][j].b;
//灰度计算公式
pixelDatatemp1[i][j]=n;
//统计每个级别的灰度值的像素的个数
graytable[n]++;
}
}
for(int i=0;i<=255;i++)
{
colortable[i].rgbBlue=i;
colortable[i].rgbGreen=i;
colortable[i].rgbRed=i;
colortable[i].rgbReserved=0;
}
image2.SetColorTable(0,256,colortable); //设置image2调色板色盘,设置色盘后才能
//确定某一像素的值,与色盘的索引值相对应,读取其真正的灰度值
CRect rect;
m_outline.GetClientRect(&rect); //m_picture为Picture Control控件变量,获得控件的区域对象
CDC * pDC=GetDlgItem(IDC_OUTLINE)->GetDC();
pDC->SetStretchBltMode(STRETCH_HALFTONE);
image2.Draw( pDC -> m_hDC,rect); //图片类的图片绘制Draw函ReleaseDC(pDC);
free(pixelData);
free(pixelDatatemp1);
CClientDC dc(this);
CRect rect_ctr;
CRect m_rect(310,290,566,488);
const int x0=310,y0=290,x1=566,y1=488;
dc. FillSolidRect(& m_rect,RGB(255,255,255));
const int N = 256;
float dx = (x1-x0)/N;//数据的个数及条图的宽度
t_max1=graytable[0];
for(int r=1;r<256;r++)
{
if(t_max1<graytable[r])
t_max1=graytable[r]; //统计256个色阶级别中,像素最大点的级别色阶
}
int a=t_max1;
CBrush br;
int s,x;
for (s= 0,x=x0;s<N;++s,x+=dx)
{
br.CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0));
dc.SelectObject(&br);
dc.Rectangle(x,488-((graytable[s]/t_max1*198)),x+dx,488);
float j=((graytable[s]/t_max1));
dc.SelectStockObject(WHITE_BRUSH);
br.DeleteObject();
}
for (int i=0;i<256;i++)
{
graytable[i]=0;
}
}
4.DLG中添加按键,caption改为auotocolororder,其代码如下。灰度自动色阶图及直方图
oid ChistogDlg::OnBnClickedAuto()
{
// TODO: 在此添加控件通知处理程序代码
BYTE *pData1=NULL;
BYTE *pData2=NULL;
unsigned char n;
unsigned char m;
CImage image2;
RGBQUAD colortable[256];
image2.Destroy(); //先销毁图片,在重新创建,避免不停打开图片,出现问题
image2.Create(image.GetWidth(),image.GetHeight(),image.GetBPP()/3,0);
if(image.GetPitch()<0)
pData1=(BYTE*)image.GetBits()+(image.GetPitch()*(image.GetHeight()-1));
else
pData1=(BYTE*)image.GetBits();
if(image2.GetPitch()<0)
pData2=(BYTE*)image2.GetBits()+(image2.GetPitch()*(image2.GetHeight()-1));
else
pData2=(BYTE*)image2.GetBits();
IAMGE_PIXEL **pixelData= (IAMGE_PIXEL**) malloc(image.GetWidth() *image2.GetHeight() * 3);
unsigned char **pixelDatatemp1= (unsigned char **) malloc(image2.GetWidth() *image2.GetHeight() );
memset(pixelDatatemp1,0,image2.GetWidth() *image2.GetHeight());
memset(pixelData,0,image2.GetWidth() *image2.GetHeight());
for (int i=0; i<image2.GetHeight(); i++)
{
pixelData[i] =(IAMGE_PIXEL *) (pData1 + image.GetWidth()*i*3);
pixelDatatemp1[i]=(unsigned char *) ( pData2+image2.GetWidth()*i);
}
for(int i=0; i<image.GetHeight();i++)
{
for( int j=0; j<image.GetWidth();j++)
{
n=0.59*pixelData[i][j].g+0.3*pixelData[i][j].r+0.11*pixelData[i][j].b;
pixelDatatemp1[i][j]=n;
graytable[n]++; //得到灰度每个级别像素点的个数,保存在这个数组中
}
}
//找出这个数组中从0到255个级别中,第一个非零值,并记下这个级别,设置为最小色阶点
for(int i=0;i<=255;i++)
{
if(graytable[i]!=0)
{
color_min =graytable[i];
color_downsub=i;
break;
}
}
//找出这个数组中从255到0个级别中,第一个非零值,并记下这个级别,设置为最大色阶点
for(int i=255;i>=0;i--)
{
if(graytable[i]!=0)
{
color_max =graytable[i];
color_upsub=i;
break;
}
}
//从最小色阶点开始选择整个图像总点数的5.5%的那一点做为新的最小点,
for( color_downsub;color_downsub<256;color_downsub++)
{
float totalpiex=image2.GetWidth()*image2.GetHeight();
color_newmin+=graytable[color_downsub];
if(color_newmin/totalpiex>0.055)
{
color_newdownsub=color_downsub;
break;
}
}
//再沿相反方向(即255阶->0阶方向)选择整个图像总点数的5.5%的那一点做为新的最大点NewMax
for( color_upsub;color_upsub>0;color_upsub--)
{
float totalpiex=image2.GetWidth()*image2.GetHeight();
color_newmax+=graytable[color_upsub];
if(color_newmax/totalpiex>0.055)
{
color_newupsub=color_upsub;
break;
}
}
//计算先的最小色阶点和新值最大色阶点两者之差为Differ
colordiffer=abs((color_newupsub-color_newdownsub));
//则每以原始像素点对应的新值可以按如下算法计算
for(int i=0; i<image2.GetHeight();i++)
{
for( int j=0; j<image2.GetWidth();j++)
{
if( pixelDatatemp1[i][j]<color_newdownsub)
pixelDatatemp1[i][j]=0;
else if( pixelDatatemp1[i][j]>color_newupsub)
pixelDatatemp1[i][j]=255;
else
pixelDatatemp1[i][j]=( (pixelDatatemp1[i][j]-color_newdownsub)*255/colordiffer);
}
}
//因为是8为深度的图形,所以要将其选入色盘
for(int i=0;i<=255;i++)
{
colortable[i].rgbBlue=i;
colortable[i].rgbGreen=i;
colortable[i].rgbRed=i;
colortable[i].rgbReserved=0;
}
image2.SetColorTable(0,256,colortable);
CRect rect1;
m_outline.GetClientRect(&rect1); //m_picture为Picture Control控件变量,获得控件的区域对象
CDC * pDC1=GetDlgItem(IDC_OUTLINE)->GetDC();
pDC1->SetStretchBltMode(STRETCH_HALFTONE);
image2.Draw( pDC1 -> m_hDC,rect1); //图片类的图片绘制Draw函ReleaseDC(pDC);
for(int i=0; i<image2.GetHeight();i++)
{
for( int j=0; j<image2.GetWidth();j++)
{
autotable[ pixelDatatemp1[i][j]]++;
}
}
CClientDC dc(this);
CRect rect_ctr;
CRect m_rect(310,290,566,488);
const int x0=310,y0=290,x1=566,y1=488;
dc. FillSolidRect(& m_rect,RGB(255,255,255));
const int N = 256;
float dx = (x1-x0)/N;//数据的个数及条图的宽度
t_max1=autotable[0];
for(int r=1;r<256;r++)
{
if(t_max1<autotable[r])
t_max1=autotable[r];
}
int a=t_max1;
CBrush br;
int s,x;
for (s= 0,x=x0;s<N;++s,x+=dx)
{
br.CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0));
dc.SelectObject(&br);
dc.Rectangle(x,488-((autotable[s]/t_max1*198)),x+dx,488);
float j=((autotable[s]/t_max1));
dc.SelectStockObject(WHITE_BRUSH);
br.DeleteObject();
}
for(int i=0;i<256;i++)
autotable[i]=0;
for(int i=0;i<256;i++)
graytable[i]=0;
free(pixelData);
free(pixelDatatemp1);
}
5.DLG中添加按键,caption改为auotohistogram,其代码如下,对图像中的r,g ,b值做处理,代码如下
void ChistogDlg::OnBnClickedAutohistog()
{
// TODO: 在此添加控件通知处理程序代码
BYTE *pData1=NULL;
BYTE *pData2=NULL;
unsigned char n;
unsigned char m;
CImage image2;
image2.Create(image.GetWidth(),image.GetHeight(),image.GetBPP(),0);
if(image.GetPitch()<0)
pData1=(BYTE*)image.GetBits()+(image.GetPitch()*(image.GetHeight()-1));
else
pData1=(BYTE*)image.GetBits();
if(image2.GetPitch()<0)
pData2=(BYTE*)image2.GetBits()+(image2.GetPitch()*(image2.GetHeight()-1));
else
pData2=(BYTE*)image2.GetBits();
IAMGE_PIXEL **pixelData= (IAMGE_PIXEL**) malloc(image.GetWidth() *image2.GetHeight() * 3);
IAMGE_PIXEL **pixelDatatemp1= (IAMGE_PIXEL**) malloc(image2.GetWidth() *image2.GetHeight()*3 );
memset(pixelDatatemp1,0,image2.GetWidth() *image2.GetHeight()*3);
for (int i=0; i<image2.GetHeight(); i++)
{
pixelData[i] =(IAMGE_PIXEL *) (pData1 + image.GetWidth()*i*3);
pixelDatatemp1[i]=(IAMGE_PIXEL *) ( pData2+image2.GetWidth()*i*3);
}
float pxdatar1[256]={0};
float pxdatarg1[256]={0};
float pxdatarb1[256]={0};
for(int i=0; i<image.GetHeight();i++)
{
for( int j=0; j<image.GetWidth();j++)
{
pixelDatatemp1[i][j].g= pixelData[i][j].g;
pixelDatatemp1[i][j].r= pixelData[i][j].r;
pixelDatatemp1[i][j].b= pixelData[i][j].b;
pxdatar1[(pixelDatatemp1[i][j].r)]++; //统计r每个级别的像素的总数
pxdatarg1[(pixelDatatemp1[i][j].g)]++;
pxdatarb1[(pixelDatatemp1[i][j].b)]++;
}
}
float pxdatar2[256]={0};
float pxdatarg2[256]={0};
float pxdatarb2[256]={0};
float totalpiex=image2.GetWidth()*image2.GetHeight();
//求每一个r,g,b值的每个色阶像素的个数占整个像素的百分比
for(int i=0;i<256;i++)
{
pxdatar2[i]=pxdatar1[i]/totalpiex;
pxdatarg2[i]=pxdatarg1[i]/totalpiex;
pxdatarb2[i]=pxdatarb1[i]/totalpiex;
}
float pxdatar3[256]={0};
float pxdatarg3[256]={0};
float pxdatarb3[256]={0};
//归一法, pxdatar3[i]等于 pxdatar3[0]到 pxdatar3[i}的百分比之和。
for(int i=0;i<256;i++)
{
for(int j=0;j<i;j++)
{
pxdatar3[i]+=pxdatar2[j];
pxdatarg3[i]+=pxdatarg2[j];
pxdatarb3[i]+=pxdatarb2[j];
}
}
for(int i=0; i<image.GetHeight();i++)
{
for( int j=0; j<image.GetWidth();j++)
{
//通过算法改变每一像素的r、g、b的值
pixelDatatemp1[i][j].r= 255*pxdatar3[pixelData[i][j].r];
pixelDatatemp1[i][j].g= 255*pxdatarg3[pixelData[i][j].g];
pixelDatatemp1[i][j].b= 255*pxdatarb3[pixelData[i][j].b];
}
}
CRect rect1;
m_outline.GetClientRect(&rect1); //m_picture为Picture Control控件变量,获得控件的区域对象
CDC * pDC1=GetDlgItem(IDC_OUTLINE)->GetDC();
pDC1->SetStretchBltMode(STRETCH_HALFTONE);
image2.Draw( pDC1 -> m_hDC,rect1); //图片类的图片绘制Draw函ReleaseDC(pDC);
free(pixelData);
free(pixelDatatemp1);
}
最后要画出其直方图,需要将其先转换为灰度值,在画其灰度图像的直方图。
- 画直方图,自动色阶
- 画直方图
- 画直方图
- pylab 画直方图,numpy画直方图。
- R画直方图
- ASP.NET画直方图
- [matlab] matlab 画直方图
- MatLab 画直方图
- numpy 画直方图
- 画数组的直方图
- opencv画直方图
- 用Matlab画直方图
- 画直方图(hist)
- 海龟绘图--画直方图
- 用R画直方图
- matlab 图片画直方图
- R画直方图
- 直方图
- Android应用经典主界面框架之一:仿QQ (使用Fragment, 附源码)
- 用最基本的弗洛伊德算法求1到n的最短路径
- 下拉列表根据所选Item选中某个值
- Redis监控技巧
- 【ExtJS】图片编辑器imagefield
- 画直方图,自动色阶
- 理解矩阵
- vc读写注册表实例
- 安全性测试工具AWS
- 【java learning】Something for Class String
- Android/iso客户端与服务器安全通信(Oauth2.0+3DES+RSA)
- 实木家具销售,进口实木家具,北欧篱笆提供高品质家具服务
- SQL Server Transact-SQL 编程
- android 仿微信聊天界面,以及语音录制功能