本帖最后由 yuquan08 于 2013-9-27 21:44 编辑
- #include "windows.h"
- #include<Winbase.h>
- #include "stdio.h"
- #define BLOCK_DIM 16
- unsigned char *pBmpBuf;//读入图像数据
- int bmpWidth;
- int bmpHeight;
- RGBQUAD *pColorTable;
- int biBitCount;//每个像素所占的位数
- //----------经变换后图像的数据----------------
- unsigned char *m_pImgDataOut;
- int m_imgWidthOut;
- int m_imgHeightOut;
- int m_nBitCount;
- //---------------------------------------------
- /*图像读取函数*/
- bool readBmp(char *bmpName)
- {
- FILE *fp=fopen(bmpName,"rb");//以只读的方式打开
- if (fp==0)
- return 0;
- //跳过文件头BITMAPFILEHEADER
- fseek(fp,sizeof(BITMAPFILEHEADER),0);
- //定义位图信息头结构变量,读取位图信息图信息,
- BITMAPINFOHEADER head;
- fread(&head,sizeof(BITMAPINFOHEADER),1,fp);
- bmpWidth=head.biWidth;
- bmpHeight=head.biHeight;
- biBitCount=head.biBitCount;
- //定义变量,计算每行所占的字节数
- int lineByte=(bmpWidth*biBitCount/8+3)/4*4;
- //灰度图还有颜色表,且颜色表项是256
- if(biBitCount==8)
- {
- pColorTable=new RGBQUAD[256];
- fread(pColorTable,sizeof(RGBQUAD),256,fp);
- }
- //申请位图数据所需要的空间,读位图数据进内存;
- pBmpBuf=new unsigned char[lineByte*bmpHeight];
- fread(pBmpBuf,1,lineByte*bmpHeight,fp);
- return 1;
- }
- //图像的转置函数
- bool cpuzhuanzhi()
- {
- if(m_pImgDataOut!=NULL)
- {
- delete []m_pImgDataOut;
- m_pImgDataOut=NULL;
- }
- //输出图像的高和宽
- m_imgWidthOut=bmpWidth;
- m_imgHeightOut=bmpHeight;
- m_nBitCount=biBitCount;
- //每行像素的字节数,输出图像和输入图像相等
- int lineByte=(bmpWidth*m_nBitCount/8+3)/4*4;
- //申请缓冲区,存放输出结果
- m_pImgDataOut=new unsigned char[lineByte*bmpHeight];
- //置黑色
- memset(m_pImgDataOut,0,lineByte*bmpHeight);
- //循环变量,图像坐标
- int i,j;
- //循环变量,每个像素的通道
- int k;
- //每个像素的字节数,输出图像与输入图像相等
- int pixelByte=m_nBitCount/8;
- //转置运算
- for (i=0;i<bmpHeight;i++)
- {
- for (j=0;j<bmpWidth;j++)
- {
- for(k=0;k<pixelByte;k++)
- *(m_pImgDataOut+i*lineByte+j*pixelByte+k)=*(pBmpBuf
- +j*lineByte+i*pixelByte+k);
- }
- }
- return TRUE;
- }
- //GPU上转置函数的实现
- __global__ void gpuzhuanzhi(unsigned char*g_iImageData,unsigned char*g_oImageData,
- int d_bmpWidth,int d_bmpHeight)
- {
- unsigned int xIndex=blockDim.x*blockIdx.x+threadIdx.x;
- unsigned int yIndex=blockDim.y*blockIdx.y+threadIdx.y;
- if (xIndex<d_bmpWidth&&yIndex<d_bmpHeight)
- {
- unsigned int index_in=xIndex+d_bmpWidth*yIndex;//按行索引
- unsigned int index_out=yIndex+d_bmpHeight*xIndex;//按列索引
- g_oImageData[index_out]=g_iImageData[index_in];
- }
- }
- /*图像保存函数*/
- bool saveBmp(char*bmpName,unsigned char*imgBuf,int width,int height,int biBitCount,
- RGBQUAD*pColorTable)
- {
- if (!imgBuf)
- return 0;
- int colorTablesize=0;
- if(biBitCount==8)
- colorTablesize=1024;
- //待存储的图像的数据的每行的字节数
- int lineByte=(width*biBitCount/8+3)/4*4;
- //以二进制写的方式打开文件
- FILE*fp=fopen(bmpName,"wb");
- if(fp==0)
- return 0;
- //申请位图文件头变量,将信息写入位图文件头
- BITMAPFILEHEADER fileHead;
- fileHead.bfType=0x4D42;
- //bfSize是图像文件的四部分之和
- fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
- +colorTablesize+lineByte*height;
- fileHead.bfReserved1=0;
- fileHead.bfReserved2=0;
- //bfOffBits是图像前三部分之和
- fileHead.bfOffBits=54+colorTablesize;
- //写文件头进文件
- fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);
- //申请位图信息头结构变量,填写信息头信息
- BITMAPINFOHEADER head;
- head.biBitCount=biBitCount;
- head.biClrImportant=0;
- head.biClrUsed=0;
- head.biCompression=0;
- head.biHeight=height;
- head.biPlanes=1;
- head.biSize=40;
- head.biSizeImage=lineByte*height;
- head.biWidth=width;
- head.biXPelsPerMeter=0;
- head.biYPelsPerMeter=0;
- //写位图信息头进内存
- fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);
- //如果灰度图像,有颜色表,写入文件
- if(biBitCount==8)
- fwrite(pColorTable,sizeof(RGBQUAD),256,fp);
- //写位图数据进文件
- fwrite(imgBuf,height*lineByte,1,fp);
- //关闭文件
- fclose(fp);
- return 1;
-
- }
- //--------------------图像转置主函数----------------------
- void main()
- {
- char readPath[]="lena.bmp";
- readBmp(readPath);
-
- //输出图像的信息
- printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpHeight,biBitCount);
- //------------------------cpu转置----------------------------
- //CPU转置后的结果保存在文件里lenaCPU.bmp
- /************************cpu测时前准备**************************/
- LARGE_INTEGER litmp;
- LONGLONG QPart1,QPart2;
- double dfMinus, dfFreq, dfTim;
- QueryPerformanceFrequency(&litmp); //获得计数器的时钟频率
- dfFreq = (double)litmp.QuadPart;
- QueryPerformanceCounter(&litmp); //获得初始值
- QPart1 = litmp.QuadPart;
- /**********************以下为待测程序区**********************/
- cpuzhuanzhi();
- /*************************测时结束***************************/
- QueryPerformanceCounter(&litmp); //获得终止值
- QPart2 = litmp.QuadPart;
- dfMinus = (double)(QPart2-QPart1);
- dfTim = dfMinus / dfFreq;
- printf( "Time to run this program is %f CPU_Clock\n",dfMinus);
- printf( "Time to run this program is %f seconds\n",dfTim);
- char writePath[]="lenaCPU.bmp";
- saveBmp(writePath,m_pImgDataOut,bmpWidth,bmpHeight,biBitCount,pColorTable);
- //---------------对函数进行计时,采用GPU进行转置,并且将文件存储在lenaGpu.bmp----------------
-
- //定义变量,计算每行所占的字节数
- int lineByte=(bmpWidth*biBitCount/8+3)/4*4;
- //-------------为设备端分配显存-----------------------------------
- unsigned char *d_iImageData;
- cudaMalloc((void**)&d_iImageData,lineByte*bmpHeight);
- unsigned char *d_oImageData;
- cudaMalloc((void**)&d_oImageData,lineByte*bmpHeight);
- //--------将内存中的图像的 数据拷贝到显存中----------------------------------
- cudaMemcpy(d_iImageData,pBmpBuf,lineByte*bmpHeight,cudaMemcpyHostToDevice);
- //设置运行参数,即网格的形状和线程块的形状
- dim3 block(BLOCK_DIM,BLOCK_DIM,1);
- dim3 grid(bmpWidth/BLOCK_DIM,bmpHeight/BLOCK_DIM,1);
- //--------------gpu计时函数---------------------------------------------------
- cudaEvent_t start,stop;
- cudaEventCreate(&start);
- cudaEventCreate(&stop);
- float time;
- cudaEventRecord( start, 0 );
- //------------主要的内核函数----------------------------------------------
- gpuzhuanzhi<<<grid,block>>>(d_iImageData,d_oImageData,bmpWidth,bmpHeight);
- cudaEventRecord( stop, 0 );
- cudaEventSynchronize( stop );
- cudaEventElapsedTime( &time, start, stop );
- cudaEventDestroy(start);
- cudaEventDestroy(stop );
- printf("Time to run on GPU is %f second",tiime);
- //-----------将显存里的计算结果写入内存-------------------------------------------
- cudaMemcpy(m_pImgDataOut,d_oImageData,lineByte*bmpHeight,cudaMemcpyDeviceToHost);
- //------将GPU的计算结果写入图像文件----------------------------------
- char writePath[]="lenaGPU.bmp";
- saveBmp(writePath,m_pImgDataOut,m_imgWidthOut,m_imgHeightOut,m_nBitCount,pColorTable);
- cudaFree(d_iImageData);
- cudaFree(d_oImageData);
- //---------------------------------------------------------------------------------------
- delete[]m_pImgDataOut;
- if(m_nBitCount==8)
- delete[]pColorTable;
-
- }
复制代码
|