使用StretchBlt函数进行图像缩放

71 篇文章 0 订阅
3 篇文章 0 订阅


点击打开链接

(2011-10-09 19:12:51)

// Resize CImage
void CreateStretchImage(CImage *pImage,CImage *ResultImage,int StretchHeight,int StretchWidth){
    if(pImage->IsDIBSection()){
          // 取得 pImage 的 DC
  CDC* pImageDC1 = CDC::FromHandle(pImage->GetDC()); // Image 因為有自己的 DC, 所以必須使用 FromHandle 取得對應的 DC

  


  CBitmap *bitmap1=pImageDC1->GetCurrentBitmap();
  BITMAP bmpInfo;
  bitmap1->GetBitmap(&bmpInfo);

  // 建立新的 CImage
  ResultImage->Create(StretchWidth,StretchHeight,bmpInfo.bmBitsPixel);
  CDC* ResultImageDC = CDC::FromHandle(ResultImage->GetDC());

  // 當 Destination 比較小的時候, 會根據 Destination DC 上的 Stretch Blt mode 決定是否要保留被刪除點的資訊
  ResultImageDC->SetStretchBltMode(HALFTONE); // 使用最高品質的方式
  ::SetBrushOrgEx(ResultImageDC->m_hDC,0,0,NULL); // 調整 Brush 的起點

  // 把 pImage 畫到 ResultImage 上面
  StretchBlt(*ResultImageDC,0,0,StretchWidth,StretchHeight,*pImageDC1,0,0,pImage->GetWidth(),pImage->GetHeight(),SRCCOPY);
  // pImage->Draw(*ResultImageDC,0,0,StretchWidth,StretchHeight,0,0,pImage->GetWidth(),pImage->GetHeight());

  pImage->ReleaseDC();
  ResultImage->ReleaseDC();
     }
}

// 建立指定大小的圖形
// 輸入: 原始圖檔=pBitmap, 指定大小=StretchHeight StretchWidth, 結果圖檔=pResultBmp
// Usage:

void reateStretchBmp(CBitmap* pBitmap ,int StretchHeight ,int StretchWidth, CBitmap *pResultBmp){
 // 建立顯示螢幕的 DC
 CDC dcScreen;
        dcScreen.Attach(::GetDC(NULL));

 // 取得原始圖檔的 dc
 CDC dcMemory;
        dcMemory.CreateCompatibleDC(&dcScreen);
 CBitmap *pOldOrgBitmap= dcMemory.SelectObject(pBitmap);
 
 // 建立新的結果圖形 (指定大小)
 pResultBmp->CreateCompatibleBitmap(&dcScreen,StretchWidth,StretchHeight);

 // 取得結果圖形的 dc
 CDC dcFixMemory;
 dcFixMemory.CreateCompatibleDC(&dcScreen);
 CBitmap *pOldReslutBitmap=dcFixMemory.SelectObject(pResultBmp); // 讓 dcFixMemory 選擇到 "結果bmp", 任何對 dcFixMemory 的動作都會反映到 pResultBmp

 // 把原始圖形縮放畫到 Memory DC上面
 BITMAP bmpInfo;
 pBitmap->GetBitmap(&bmpInfo); // 取得 原始圖檔的寬度與高度
 StretchBlt(dcFixMemory,0,0,StretchWidth,StretchHeight,dcMemory,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY);

 // Set Back
 dcMemory.SelectObject(pOldOrgBitmap);
 dcFixMemory.SelectObject(pOldReslutBitmap);
}

 


 

那位朋友用过图行缩放中的插值算法,我原来的做法是把整个图片内容读到内存中,然后用插值算法做缩放,这样是可行的。但由于我现在需要做内存优化,源数据需要一行一行的读,我的思路是读一行数据,用插值算法做一次转换,但由于插值算法需要参考周围4个点的数据做插值,所以我不确定我现在的思路是不是可行,哪位朋友做过这方面的工作?

我对整个图片做缩放的代码如下:
unsigned char* HCNImage::do_Stretch_Linear(int w_Dest,int h_Dest,int bit_depth,unsigned char *src,int w_Src,int h_Src)
{
int sw = w_Src-1, sh = h_Src-1, dw = w_Dest-1, dh = h_Dest-1;
int B, N, x, y;
int nPixelSize = bit_depth/8;
unsigned char *pLinePrev,*pLineNext;
unsigned char *pDest = new unsigned char[w_Dest*h_Dest*bit_depth/8];
unsigned char *tmp;
unsigned char *pA,*pB,*pC,*pD;

for(int i=0;i<=dh;++i)
{
tmp =pDest + i*w_Dest*nPixelSize;
y = i*sh/dh;
N = dh - i*sh%dh;
pLinePrev = src + (y++)*w_Src*nPixelSize;

pLineNext = (N==dh) ? pLinePrev : src+y*w_Src*nPixelSize;

for(int j=0;j<=dw;++j)
{
x = j*sw/dw*nPixelSize;
B = dw-j*sw%dw;
pA = pLinePrev+x;
pB = pA+nPixelSize;
pC = pLineNext + x;
pD = pC + nPixelSize;
if(B == dw)
{
pB=pA;
pD=pC;
}

for(int k=0;k<nPixelSize;++k)
{
*tmp++ = ( unsigned char )( int )(
( B * N * ( *pA++ - *pB - *pC + *pD ) + dw * N * *pB++
+ dh * B * *pC++ + ( dw * dh - dh * B - dw * N ) * *pD++
+ dw * dh / 2 ) / ( dw * dh ) );
}
}
}
return pDest;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值