C 研发中数据结构和算法的分离

2008-02-23 05:24:52来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

 相信每一个在windows下编过程式的人都或多或少地用过位图,大多数人是从网上下载一些成熟完善的DIB类库来使用(例如CxImage、CDIB),少数人有一套自己封装好的DIB类库,方便以后的扩充和使用。(近几年GDI 异军突起,在某些处理方面,如:缩放、旋转、渐变填充等他提供无和伦比的速度和质量,但,假如您想做一个完善的图像处理程式,直接使用他会给架构设计带来困难,您能够用adapter模式封装他后再使用)。

  这时候,假如您需要一些图像处理操作您会怎么办呢?很多没有OO经验的C 程式员(例如一年前的我)可能会这样做:在类中直接添加方法。

//================================================================
int FClamp0255 (int nValue) {return max (0, min (0xFF, nValue));} // 饱和到0--255

class FCObjImage
{
 public :
  Invert () ;
  AdjustRGB (int R, int G, int B) ;

} ;
//================================================================
void FCObjImage::Invert ()
{
 if ((GetHandle() == NULL) || (ColorBits() < 24))
  return ;

 int nSpan = ColorBits() / 8 ; // 每象素字节数3, 4
 for (int y=0 ; y < Height() ; y )
 {
  BYTE * pPixel = GetBits (y) ;
  for (int x=0 ; x < Width() ; x , pPixel = nSpan)
  {
   pPixel[0] = ~pPixel[0] ;
   pPixel[1] = ~pPixel[1] ;
   pPixel[2] = ~pPixel[2] ;

  }
 }
}
//================================================================
void FCObjImage::AdjustRGB (int R, int G, int B)
{
 if ((GetHandle() == NULL) || (ColorBits() < 24))
  return ;

 int nSpan = ColorBits() / 8 ; // 每象素字节数3, 4
 for (int y=0 ; y < Height() ; y )
 {
  BYTE * pPixel = GetBits (y) ;
  for (int x=0 ; x < Width() ; x , pPixel = nSpan)
  {
   pPixel[0] = FClamp0255 (pPixel[0] B) ;
   pPixel[1] = FClamp0255 (pPixel[1] G) ;
   pPixel[2] = FClamp0255 (pPixel[2] R) ;

  }
 }
}
//================================================================

  这里举了两个例子(分别实现反色,调节RGB值功能),现实中会有大量的此类操作:亮度、对比度、饱和度......现在回想一下,您添加这些方法的步骤是什么,Ooooooooo,RCP(我同事的发明,全称:rapid copy paste^-^),第一步一定是从上面复制一块代码下来,然后改掉其中的接口和处理部分。虽然这里的示范代码很短小,不会连同bug一起复制,但,定时炸弹却又多了一个。有天,您的boss告诉您:我不能忍受长时间的等待,请给我加个进度条.....。您也许会加个全局变量,也许会给每个函数加个参数,但不变的是:您必须修改任何这些处理函数的代码,内心的咒骂并不会使您少改其中的任何一个。而此时,bug已在旁边伺机而动了...然而苦日子远没熬到头,一个月后,您心血来潮的老板会让您在其中加上区域处理的功能,再一个月后......

  回头重新看看代码?没错,除了红色的代码外,其他地方一摸相同,那能不能把这些算法分离抽出来呢?可能我们马上会想到标准库中qsort和windows中常用的回调方法。好,让我们实作一下:

//================================================================void Pixel_Invert (BYTE * pPixel)
{
 pPixel[0] = ~pPixel[0] ;
 pPixel[1] = ~pPixel[1] ;
 pPixel[2] = ~pPixel[2] ;

}
//================================================================
void FCObjImage::PixelProcess (void(__cdecl*PixelProc)(BYTE * pPixel))
{
 if ((GetHandle() == NULL) || (ColorBits() < 24))
  return ;

 int nSpan = ColorBits() / 8 ; // 每象素字节数3, 4
 for (int y=0 ; y < Height() ; y )
 {
  BYTE * pPixel = GetBits (y) ;
  for (int x=0 ; x < Width() ; x , pPixel = nSpan)
  {
   PixelProc (pPixel) ;
  }
 }
}
//================================================================
void FCObjImage::Invert ()
{
 PixelProcess (Pixel_Invert) ;
}
//================================================================

 相信每一个在windows下编过程式的人都或多或少地用过位图,大多数人是从网上下载一些成熟完善的DIB类库来使用(例如CxImage、CDIB),少数人有一套自己封装好的DIB类库,方便以后的扩充和使用。(近几年GDI 异军突起,在某些处理方面,如:缩放、旋转、渐变填充等他提供无和伦比的速度和质量,但,假如您想做一个完善的图像处理程式,直接使用他会给架构设计带来困难,您能够用adapter模式封装他后再使用)。

  这时候,假如您需要一些图像处理操作您会怎么办呢?很多没有OO经验的C 程式员(例如一年前的我)可能会这样做:在类中直接添加方法。

//================================================================
int FClamp0255 (int nValue) {return max (0, min (0xFF, nValue));} // 饱和到0--255

class FCObjImage
{
 public :
  Invert () ;
  AdjustRGB (int R, int G, int B) ;

} ;
//================================================================
void FCObjImage::Invert ()
{
 if ((GetHandle() == NULL) || (ColorBits() < 24))
  return ;

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 深入剖析C 重载函数的应用

下一篇: C 虚函数和动态联编技术分析