用户
 找回密码
 立即注册
回帖奖励 10 CUDA币 回复本帖可获得 10 CUDA币奖励! 每人限 2 次
yuquan08 该用户已被删除
发表于 2013-9-27 20:24:01
62440
本帖最后由 yuquan08 于 2013-9-27 21:44 编辑
  1. #include "windows.h"
  2. #include<Winbase.h>
  3. #include "stdio.h"

  4. #define BLOCK_DIM  16

  5. unsigned char *pBmpBuf;//读入图像数据
  6. int bmpWidth;
  7. int bmpHeight;
  8. RGBQUAD *pColorTable;
  9. int biBitCount;//每个像素所占的位数

  10. //----------经变换后图像的数据----------------
  11. unsigned char *m_pImgDataOut;
  12. int m_imgWidthOut;
  13. int m_imgHeightOut;
  14. int m_nBitCount;
  15. //---------------------------------------------
  16. /*图像读取函数*/
  17. bool readBmp(char *bmpName)
  18. {
  19.      FILE *fp=fopen(bmpName,"rb");//以只读的方式打开
  20.         if (fp==0)
  21.         return 0;
  22.         //跳过文件头BITMAPFILEHEADER
  23.         fseek(fp,sizeof(BITMAPFILEHEADER),0);
  24.         //定义位图信息头结构变量,读取位图信息图信息,
  25.         BITMAPINFOHEADER head;
  26.         fread(&head,sizeof(BITMAPINFOHEADER),1,fp);
  27.         bmpWidth=head.biWidth;
  28.         bmpHeight=head.biHeight;
  29.         biBitCount=head.biBitCount;
  30.         //定义变量,计算每行所占的字节数
  31.         int lineByte=(bmpWidth*biBitCount/8+3)/4*4;
  32.         //灰度图还有颜色表,且颜色表项是256
  33.         if(biBitCount==8)
  34.         {
  35.                 pColorTable=new RGBQUAD[256];
  36.                 fread(pColorTable,sizeof(RGBQUAD),256,fp);

  37.         }
  38.         //申请位图数据所需要的空间,读位图数据进内存;
  39.         pBmpBuf=new unsigned char[lineByte*bmpHeight];

  40.         fread(pBmpBuf,1,lineByte*bmpHeight,fp);
  41.         return 1;
  42. }
  43. //图像的转置函数
  44. bool cpuzhuanzhi()
  45. {
  46.         if(m_pImgDataOut!=NULL)
  47.         {
  48.                 delete []m_pImgDataOut;
  49.         m_pImgDataOut=NULL;
  50.         }
  51.         //输出图像的高和宽
  52.         m_imgWidthOut=bmpWidth;
  53.         m_imgHeightOut=bmpHeight;
  54.         m_nBitCount=biBitCount;
  55.         //每行像素的字节数,输出图像和输入图像相等
  56.         int lineByte=(bmpWidth*m_nBitCount/8+3)/4*4;
  57.         //申请缓冲区,存放输出结果
  58.         m_pImgDataOut=new unsigned char[lineByte*bmpHeight];
  59.         //置黑色
  60.         memset(m_pImgDataOut,0,lineByte*bmpHeight);
  61.         //循环变量,图像坐标
  62.         int i,j;
  63.         //循环变量,每个像素的通道
  64.         int k;
  65.         //每个像素的字节数,输出图像与输入图像相等
  66.         int pixelByte=m_nBitCount/8;
  67.         //转置运算
  68.         for (i=0;i<bmpHeight;i++)
  69.         {
  70.                 for (j=0;j<bmpWidth;j++)
  71.                 {
  72.                         for(k=0;k<pixelByte;k++)
  73.                         *(m_pImgDataOut+i*lineByte+j*pixelByte+k)=*(pBmpBuf
  74.                                 +j*lineByte+i*pixelByte+k);
  75.                 }
  76.         }
  77.         return TRUE;


  78. }
  79. //GPU上转置函数的实现
  80. __global__ void gpuzhuanzhi(unsigned char*g_iImageData,unsigned char*g_oImageData,
  81.                                                  int d_bmpWidth,int d_bmpHeight)
  82. {
  83.         unsigned int xIndex=blockDim.x*blockIdx.x+threadIdx.x;
  84.         unsigned int yIndex=blockDim.y*blockIdx.y+threadIdx.y;
  85.         if (xIndex<d_bmpWidth&&yIndex<d_bmpHeight)
  86.         {
  87.                 unsigned int index_in=xIndex+d_bmpWidth*yIndex;//按行索引
  88.                 unsigned int index_out=yIndex+d_bmpHeight*xIndex;//按列索引
  89.                 g_oImageData[index_out]=g_iImageData[index_in];

  90.         }

  91. }
  92. /*图像保存函数*/
  93. bool saveBmp(char*bmpName,unsigned char*imgBuf,int width,int height,int biBitCount,
  94.                   RGBQUAD*pColorTable)
  95. {
  96.         if (!imgBuf)
  97.                 return 0;
  98.         int colorTablesize=0;
  99.         if(biBitCount==8)
  100.                 colorTablesize=1024;
  101.         //待存储的图像的数据的每行的字节数
  102.         int lineByte=(width*biBitCount/8+3)/4*4;
  103.         //以二进制写的方式打开文件
  104.         FILE*fp=fopen(bmpName,"wb");
  105.         if(fp==0)
  106.                 return 0;
  107. //申请位图文件头变量,将信息写入位图文件头
  108.         BITMAPFILEHEADER  fileHead;
  109.         fileHead.bfType=0x4D42;
  110.         //bfSize是图像文件的四部分之和
  111.         fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
  112.                 +colorTablesize+lineByte*height;
  113.         fileHead.bfReserved1=0;
  114.         fileHead.bfReserved2=0;
  115.         //bfOffBits是图像前三部分之和
  116.         fileHead.bfOffBits=54+colorTablesize;
  117.         //写文件头进文件
  118.         fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);
  119.         //申请位图信息头结构变量,填写信息头信息
  120.         BITMAPINFOHEADER head;
  121.         head.biBitCount=biBitCount;
  122.         head.biClrImportant=0;
  123.         head.biClrUsed=0;
  124.         head.biCompression=0;
  125.         head.biHeight=height;
  126.         head.biPlanes=1;
  127.         head.biSize=40;
  128.         head.biSizeImage=lineByte*height;
  129.         head.biWidth=width;
  130.         head.biXPelsPerMeter=0;
  131.         head.biYPelsPerMeter=0;
  132.         //写位图信息头进内存
  133.         fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);
  134.         //如果灰度图像,有颜色表,写入文件
  135.         if(biBitCount==8)
  136.                 fwrite(pColorTable,sizeof(RGBQUAD),256,fp);
  137.         //写位图数据进文件
  138.         fwrite(imgBuf,height*lineByte,1,fp);
  139.         //关闭文件
  140.         fclose(fp);
  141.         return 1;
  142.         
  143. }
  144. //--------------------图像转置主函数----------------------
  145. void main()
  146. {
  147.         char readPath[]="lena.bmp";
  148.         readBmp(readPath);
  149.         
  150.         //输出图像的信息
  151.         printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpHeight,biBitCount);
  152. //------------------------cpu转置----------------------------
  153.         //CPU转置后的结果保存在文件里lenaCPU.bmp

  154.         /************************cpu测时前准备**************************/
  155.         LARGE_INTEGER   litmp;  
  156.         LONGLONG   QPart1,QPart2;  
  157.         double   dfMinus,   dfFreq,   dfTim;  
  158.         QueryPerformanceFrequency(&litmp);                        //获得计数器的时钟频率  
  159.         dfFreq = (double)litmp.QuadPart;  
  160.         QueryPerformanceCounter(&litmp);                               //获得初始值
  161.         QPart1 = litmp.QuadPart;
  162.     /**********************以下为待测程序区**********************/
  163.         cpuzhuanzhi();
  164.         /*************************测时结束***************************/
  165.         QueryPerformanceCounter(&litmp);                        //获得终止值  
  166.         QPart2 = litmp.QuadPart;
  167.         dfMinus = (double)(QPart2-QPart1);
  168.         dfTim = dfMinus / dfFreq;
  169.         printf( "Time to run this program is %f CPU_Clock\n",dfMinus);
  170.         printf( "Time to run this program is %f seconds\n",dfTim);

  171.         char writePath[]="lenaCPU.bmp";
  172.         saveBmp(writePath,m_pImgDataOut,bmpWidth,bmpHeight,biBitCount,pColorTable);        

  173. //---------------对函数进行计时,采用GPU进行转置,并且将文件存储在lenaGpu.bmp----------------
  174.         
  175.         //定义变量,计算每行所占的字节数
  176.         int lineByte=(bmpWidth*biBitCount/8+3)/4*4;

  177.         //-------------为设备端分配显存-----------------------------------
  178.         unsigned char *d_iImageData;
  179.         cudaMalloc((void**)&d_iImageData,lineByte*bmpHeight);
  180.         unsigned char *d_oImageData;
  181.         cudaMalloc((void**)&d_oImageData,lineByte*bmpHeight);
  182.         //--------将内存中的图像的 数据拷贝到显存中----------------------------------
  183.         cudaMemcpy(d_iImageData,pBmpBuf,lineByte*bmpHeight,cudaMemcpyHostToDevice);
  184.         //设置运行参数,即网格的形状和线程块的形状
  185.         dim3  block(BLOCK_DIM,BLOCK_DIM,1);
  186.         dim3  grid(bmpWidth/BLOCK_DIM,bmpHeight/BLOCK_DIM,1);
  187.         //--------------gpu计时函数---------------------------------------------------
  188.         cudaEvent_t start,stop;
  189.         cudaEventCreate(&start);
  190.         cudaEventCreate(&stop);
  191.         float time;
  192.         cudaEventRecord( start, 0 );
  193.         //------------主要的内核函数----------------------------------------------        
  194.         gpuzhuanzhi<<<grid,block>>>(d_iImageData,d_oImageData,bmpWidth,bmpHeight);
  195.         cudaEventRecord( stop, 0 );
  196.         cudaEventSynchronize( stop );
  197.         cudaEventElapsedTime( &time, start, stop );
  198.         cudaEventDestroy(start);
  199.         cudaEventDestroy(stop );
  200.         printf("Time to run on GPU is %f second",tiime);
  201.         //-----------将显存里的计算结果写入内存-------------------------------------------
  202.         cudaMemcpy(m_pImgDataOut,d_oImageData,lineByte*bmpHeight,cudaMemcpyDeviceToHost);

  203.         //------将GPU的计算结果写入图像文件----------------------------------
  204.         char writePath[]="lenaGPU.bmp";
  205.         saveBmp(writePath,m_pImgDataOut,m_imgWidthOut,m_imgHeightOut,m_nBitCount,pColorTable);
  206.         cudaFree(d_iImageData);
  207.         cudaFree(d_oImageData);
  208.   //---------------------------------------------------------------------------------------
  209.         delete[]m_pImgDataOut;
  210.         if(m_nBitCount==8)
  211.                 delete[]pColorTable;
  212.         
  213. }
复制代码


使用道具 举报 回复
发新帖
您需要登录后才可以回帖 登录 | 立即注册