Chinaunix首页 | 论坛 | 博客
  • 博客访问: 39812
  • 博文数量: 6
  • 博客积分: 193
  • 博客等级: 入伍新兵
  • 技术积分: 69
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-08 13:46
文章分类

全部博文(6)

文章存档

2012年(1)

2011年(5)

我的朋友

分类: WINDOWS

2011-12-09 10:55:07

工作需要,要弄截图且缩小。截图倒是好说,WIN API可以搞定,但是缩小且尽量不失真,这个对我来说难度太大了吧。这里主要说说缩小的算法。我从网上找到两个算法分别是bilinear和nearest。但是效果看上去太差了。我先贴上处理后的三种算法效果图,然后再贴算法。

bilinear

JKE1VSDO[SA@J(9I6ZZ[RV4

nearest

TYJC3GZ~@4WZ}J0IMAY8`VK

cubic

T9547]O@N7VHL{%@DGS_Q}0

     当然大家可以看的出来,效果最好的自然是Cubic,提供一些该算法的资料,不过我自己是没看懂。cubic是我们公司多媒体方面的牛人帮我写的。


以下是代码:



  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <string>
  4. #include <windows.h>
  5. #include <math.h>
  6. using namespace std;

  7. enum StretchMode
  8. {
  9.     nearest, //最临近插值算法
  10.     bilinear, //双线性内插值算法
  11.     cubic
  12. };

  13. const int CUBIC_SIZE = 3;
  14. int getSincVec(float *pfVec, float fPos, float fScale)
  15. {
  16.     int nPos = (int)fPos;
  17.     fPos -= (float)nPos;
  18.     memset(pfVec, 0, sizeof(float) * CUBIC_SIZE);
  19.     float fSum = 0.f;
  20.     for (int i=0; i<CUBIC_SIZE; i++)
  21.     {
  22.         float fTmp = (i - 1.f + fPos) * 3.14159265358979323846f;
  23.         if (fTmp > 0.00001 || fTmp < -0.00001)
  24.         {
  25.             pfVec[i] = sinf(fTmp * fScale) / fTmp;
  26.         }
  27.         else
  28.         {
  29.             pfVec[i] = 1.f;
  30.         }
  31.         fSum += pfVec[i];
  32.     }
  33.     fSum = 1.f / fSum;
  34.     for (int i=0; i<CUBIC_SIZE; i++)
  35.     {
  36.         pfVec[i] *= fSum;
  37.     }
  38.     return nPos;
  39. }
  40. void calcSincMat(float *pfMat, float *pfVecY, float *pfVecX)
  41. {
  42.     for (int i=0; i<CUBIC_SIZE; i++)
  43.     {
  44.         for (int j=0; j<CUBIC_SIZE; j++)
  45.         {
  46.             pfMat[i * CUBIC_SIZE + j] = pfVecY[i] * pfVecX[j];
  47.         }
  48.     }
  49. }

  50. void Stretch(const string& srcFile,const string& desFile,int desW,int desH,StretchMode mode)
  51. {
  52.     BITMAPFILEHEADER bmfHeader;
  53.     BITMAPINFOHEADER bmiHeader;

  54.     FILE *pFile;
  55.     if ((pFile = fopen(srcFile.c_str(),"rb")) == NULL)
  56.     {
  57.         printf("open bmp file error.");
  58.         exit(-1);
  59.     }
  60.     //读取文件和Bitmap头信息
  61.     fseek(pFile,0,SEEK_SET);
  62.     fread(&bmfHeader,sizeof(BITMAPFILEHEADER),1,pFile);
  63.     fread(&bmiHeader,sizeof(BITMAPINFOHEADER),1,pFile);
  64.     //先不支持小于16位的位图
  65.     int bitCount = bmiHeader.biBitCount;
  66.     if (bitCount < 16)
  67.     {
  68.         exit(-1);
  69.     }
  70.     int srcW = bmiHeader.biWidth;
  71.     int srcH = bmiHeader.biHeight;

  72.     int lineSize = bitCount * srcW / 8;
  73.     //偏移量,windows系统要求每个扫描行按四字节对齐
  74.     int alignBytes = ((bmiHeader.biWidth * bitCount + 31) & ~31) / 8L
  75.         - bmiHeader.biWidth * bitCount / 8L;
  76.     //原图像缓存
  77.     int srcBufSize = lineSize * srcH;
  78.     BYTE* srcBuf = new BYTE[srcBufSize];
  79.     int i,j;
  80.     //读取文件中数据
  81.     for (i = 0; i < srcH; i++)
  82.     {
  83.         fread(&srcBuf[lineSize * i],lineSize,1,pFile);
  84.         fseek(pFile,alignBytes,SEEK_CUR);
  85.     }

  86.     //目标图像缓存
  87.     int desBufSize = ((desW * bitCount + 31) / 32) * 4 * desH;
  88.     int desLineSize = ((desW * bitCount + 31) / 32) * 4;
  89.     BYTE *desBuf = new BYTE[desBufSize];
  90.     double rateH = (double)srcH / desH;
  91.     double rateW = (double)srcW / desW;
  92.     //最临近插值算法
  93.     if (mode == nearest)
  94.     {
  95.         for (i = 0; i < desH; i++)
  96.         {
  97.             //选取最邻近的点
  98.             int tSrcH = (int)(rateH * i + 0.5);
  99.             for (j = 0; j < desW; j++)
  100.             {
  101.                 int tSrcW = (int)(rateW * j + 0.5);
  102.                 memcpy(&desBuf[i * desLineSize] + j * bmiHeader.biBitCount / 8,&srcBuf[tSrcH * lineSize] + tSrcW * bmiHeader.biBitCount / 8,bmiHeader.biBitCount / 8);
  103.             }
  104.         }
  105.     }
  106.     //双线型内插值算法
  107.     else if (mode == bilinear)
  108.     {
  109.         for (i = 0; i < desH; i++)
  110.         {
  111.             int tH = (int)(rateH * i);
  112.             int tH1 = min(tH + 1,srcH - 1);
  113.             float u = (float)(rateH * i - tH);
  114.             for (j = 0; j < desW; j++)
  115.             {
  116.                 int tW = (int)(rateW * j);
  117.                 int tW1 = min(tW + 1,srcW - 1);
  118.                 float v = (float)(rateW * j - tW);

  119.                 //f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
  120.                 for (int k = 0; k < 3; k++)
  121.                 {
  122.                     desBuf[i * desLineSize + j * bitCount / 8 + k] =
  123.                         (1 - u)*(1 - v) * srcBuf[tH * lineSize + tW * bitCount / 8 + k] +
  124.                         (1 - u)*v*srcBuf[tH1 * lineSize + tW * bitCount / 8+ k] +
  125.                         u * (1 - v) * srcBuf[tH * lineSize + tW1 * bitCount / 8 + k] +
  126.                         u * v * srcBuf[tH1 * lineSize + tW1 * bitCount / 8 + k];
  127.                 }
  128.             }
  129.         }
  130.     }
  131.     else
  132.     {
  133.         float pfVecX[CUBIC_SIZE], pfVecY[CUBIC_SIZE], pfMat[CUBIC_SIZE][CUBIC_SIZE];
  134.         int nPixelBytes = bitCount / 8;
  135.         for (i=1; i<desH-1; i++)
  136.         {
  137.             int nSrcY = getSincVec(pfVecY, rateH * i, 1.f / rateH);
  138.             for (j = 1; j < desW-1; j++)
  139.             {
  140.                 int nSrcX = getSincVec(pfVecX, rateW * j, 1.f / rateW);
  141.                 calcSincMat(pfMat[0], pfVecY, pfVecX);
  142.                 BYTE *pbyTmpDes = desBuf + i * desLineSize + j * nPixelBytes;
  143.                 BYTE *pbyTmpSrc = srcBuf + nSrcY * lineSize + nSrcX * nPixelBytes;
  144.                 for (int k = 0; k < 3; k++)
  145.                 {
  146.                     float fTmp = pbyTmpSrc[0] * pfMat[1][1];
  147.                     fTmp += pbyTmpSrc[-lineSize] * pfMat[0][1];
  148.                     fTmp += pbyTmpSrc[lineSize] * pfMat[2][1];
  149.                     fTmp += pbyTmpSrc[-nPixelBytes] * pfMat[1][0];
  150.                     fTmp += pbyTmpSrc[-nPixelBytes-lineSize] * pfMat[0][0];
  151.                     fTmp += pbyTmpSrc[-nPixelBytes+lineSize] * pfMat[2][0];
  152.                     fTmp += pbyTmpSrc[nPixelBytes] * pfMat[1][2];
  153.                     fTmp += pbyTmpSrc[nPixelBytes-lineSize] * pfMat[0][2];
  154.                     fTmp += pbyTmpSrc[nPixelBytes+lineSize] * pfMat[2][2];
  155.                     if (fTmp < 0.f) fTmp = 0.f;
  156.                     if (fTmp > 255.f) fTmp = 255.f;
  157.                     *pbyTmpDes++ = (BYTE)fTmp;
  158.                     pbyTmpSrc++;
  159.                 }
  160.             }
  161.         }
  162.     }

  163.     //创建目标文件
  164.     HFILE hfile = _lcreat(desFile.c_str(),0);
  165.     //文件头信息
  166.     BITMAPFILEHEADER nbmfHeader;
  167.     nbmfHeader.bfType = 0x4D42;
  168.     nbmfHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
  169.         + desW * desH * bitCount / 8;
  170.     nbmfHeader.bfReserved1 = 0;
  171.     nbmfHeader.bfReserved2 = 0;
  172.     nbmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  173.     //Bitmap头信息
  174.     BITMAPINFOHEADER bmi;
  175.     bmi.biSize=sizeof(BITMAPINFOHEADER);
  176.     bmi.biWidth=desW;
  177.     bmi.biHeight=desH;
  178.     bmi.biPlanes=1;
  179.     bmi.biBitCount=bitCount;
  180.     bmi.biCompression=BI_RGB;
  181.     bmi.biSizeImage=0;
  182.     bmi.biXPelsPerMeter=0;
  183.     bmi.biYPelsPerMeter=0;
  184.     bmi.biClrUsed=0;
  185.     bmi.biClrImportant=0;

  186.     //写入文件头信息
  187.     _lwrite(hfile,(LPCSTR)&nbmfHeader,sizeof(BITMAPFILEHEADER));
  188.     //写入Bitmap头信息
  189.     _lwrite(hfile,(LPCSTR)&bmi,sizeof(BITMAPINFOHEADER));
  190.     //写入图像数据
  191.     _lwrite(hfile,(LPCSTR)desBuf,desBufSize);
  192.     _lclose(hfile);
  193. }

  194. int main(int argc, char* argv[])
  195. {
  196.     FILE *pFile;
  197.     if ((pFile = fopen("e://t.bmp","rb")) == NULL)
  198.     {
  199.         printf("open bmp file error.");
  200.         return -1;
  201.     }
  202.     string srcFile("e://t.bmp");
  203.     string desFileN("e://nearest.bmp");
  204.     string desFileB("e://bilinear.bmp");;
  205.     string desFileC("e://cubic.bmp");
  206.     //Stretch(srcFile,desFileN,235,136,nearest);
  207.     //Stretch(srcFile,desFileB,235,136,bilinear);
  208.     Stretch(srcFile,desFileC,235,136,cubic);
  209.     //int alignBytes = ~31;
  210.     //printf("alignbytes : %d",alignBytes);

  211.     return 0;
  212. }


阅读(6979) | 评论(3) | 转发(2) |
给主人留下些什么吧!~~

gdyjdao2016-06-07 10:53:37

可以使用,谢谢,但有两个小问题:buf溢出,没有delete

掠辰影2013-06-25 19:27:16

想深入学习C++真的没办法吗

新手来鸟2011-12-14 01:37:52

简直太强了啊!!崇拜一下~