在纹理上写文本

        本人在开发三维视景类项目时遇到了这样的问题,需要在舰船模型上标明它的舷号,不同的船只有不同的号,而在加载模型时相同类型的船是按照同一方式加载的,于是笔者自然想到在舰艇舷号附近的纹理贴图上直接标上文本,这样舷号自然会显示出来。由于目前使用的是RGB格式的纹理,所以需要将它转成BMP格式,然后绘制文本,再转成RGB格式。
源代码如下:
EditImage.h
#include "dib.h"
/
class CEditImage : public CEdit
{
// Construction
public:
 CEditImage();

// Attributes
public:

// Operations
public:

// Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CEditImage)
 //}}AFX_VIRTUAL

// Implementation
public:
 virtual ~CEditImage();

 // Generated message map functions
protected:
 //{{AFX_MSG(CEditImage)
 afx_msg void OnPaint();
 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
 afx_msg void OnSize(UINT nType, int cx, int cy);
 //}}AFX_MSG

 DECLARE_MESSAGE_MAP()
public:
 CDib* m_pDib;
 CRect m_rect;
 COLORREF m_clrText;
 BOOL m_bShowImage;
 BOOL SetImage(CString strName);

 BOOL SaveBMPByDC(CString strFile);
private:
 CDC* m_pDC;
 CDC* m_pMemDC;
 CBitmap* m_pBitmap;

 void Convert(CString sFileName);
 void RGBtoBMP(BYTE* pRGB,int nType,int nNum);
 BYTE* m_pRGB;
 CString m_sNote;
 BOOL    m_bBlend;
public:
 BOOL WriteToRGB(CString sOriginName,CString sDestName,COLORREF clr,CRect rect,CString sNote);
};
EditImage.cpp

CEditImage::CEditImage()
{
 m_bShowImage=false;
 m_rect.left=100;
 m_rect.top=10;
 m_rect.right=200;
 m_rect.bottom=200;
 m_clrText=RGB(255,0,0);

 m_pBitmap=NULL;
 m_pDC=NULL;
 m_pMemDC=NULL;
 m_pRGB = NULL;

 m_sNote="Hello";
 m_pDib=NULL;
}

CEditImage::~CEditImage()
{

 if(m_pMemDC)
 {
  delete m_pMemDC;
 }
 if(m_pDC)
  delete m_pDC;
 if(m_pBitmap)
 {
  m_pBitmap->DeleteObject();
  delete m_pBitmap;
 }
 if(m_pRGB)
  delete m_pRGB;

 if(m_pDib)
  delete m_pDib;
}


BEGIN_MESSAGE_MAP(CEditImage, CEdit)
 //{{AFX_MSG_MAP(CEditImage)
 ON_WM_PAINT()
 ON_WM_CREATE()
 ON_WM_SIZE()
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CEditImage message handlers

void CEditImage::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 
 // TODO: Add your message handler code here
 if(m_bShowImage)
 {
  m_pMemDC->SelectObject(m_pBitmap);
  CSize cs;
  cs.cx=m_pDib->bmSize.cx;
  cs.cy=m_pDib->bmSize.cy;
  m_pDib->Stretch(m_pMemDC,CPoint(0,0),cs);
  m_pMemDC->SetTextColor(m_clrText);
  CBrush* oldBrush=(CBrush*)m_pMemDC->SelectStockObject(NULL_BRUSH);
  m_pMemDC->SetBkMode(TRANSPARENT);
  LOGFONT lfFont;
  CFont fontNew, *fontOld;
  ZeroMemory(&lfFont, sizeof(lfFont));
  lstrcpy(lfFont.lfFaceName, "Arial");
  lfFont.lfHeight = m_rect.Height();
  lfFont.lfWidth = m_rect.Width();
  fontNew.CreateFontIndirect(&lfFont);
  fontOld=m_pMemDC->SelectObject(&fontNew);
  m_pMemDC->TextOut(m_rect.left,m_rect.top,m_sNote);
  m_pDC->BitBlt(0,0,cs.cx,cs.cy,m_pMemDC,0,0,SRCCOPY);

  m_pMemDC->SelectObject(oldBrush);
  m_pMemDC->SelectObject(fontOld);
 }
}
BOOL CEditImage::SetImage(CString strName)
{
 if(m_pDib)
  delete m_pDib;
 m_pDib=new CDib();
 m_bShowImage=false;
 if(m_pDib->ReadFile(strName))
 { 
  CSize cs;
  cs.cx=m_pDib->bmSize.cx;
  cs.cy=m_pDib->bmSize.cy;
  MoveWindow(0,0,cs.cx,cs.cy,true);
  m_bShowImage=true;
  Invalidate(false);
 } 
 else
  m_bShowImage=false;

 return m_bShowImage;
}

BOOL CEditImage::SaveBMPByDC(CString strFile)
{
 
 BITMAP btm;
 m_pBitmap->GetBitmap(&btm);
 DWORD size=btm.bmWidthBytes*btm.bmHeight;
 LPSTR lpData=(LPSTR)GlobalAllocPtr(GPTR,size);
/
 BITMAPINFOHEADER bih;
 bih.biBitCount=btm.bmBitsPixel;
 bih.biClrImportant=0;
 bih.biClrUsed=0;
 bih.biCompression=0;
 bih.biHeight=btm.bmHeight;
 bih.biPlanes=1;
 bih.biSize=sizeof(BITMAPINFOHEADER);
 bih.biSizeImage=size;
 bih.biWidth=btm.bmWidth;
 bih.biXPelsPerMeter=0;
 bih.biYPelsPerMeter=0;
///
 HBITMAP bm;
 bm=(HBITMAP)m_pBitmap->GetSafeHandle();
 GetDIBits(m_pMemDC->GetSafeHdc(),bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);
// bm.GetBitmapBits(size,lpData); //此函数在处理5-5-5模式的16位色下会出现颜色混乱
//
 if(bih.biBitCount<24)
  return FALSE;
 BITMAPFILEHEADER bfh;
 bfh.bfReserved1=bfh.bfReserved2=0;
 bfh.bfType=((WORD)('M'<< 8)|'B');
 bfh.bfSize=54+size;
 bfh.bfOffBits=54;
 ///rgb/
 
 CFile bfr;
 if(bfr.Open(strFile,CFile::modeCreate|CFile::modeWrite))
 {
  int nWidth=bih.biWidth;
  int nHeight=bih.biHeight;
  byte* tmpByte;
  if(!m_bBlend)
  {  
   tmpByte=new byte[nWidth*nHeight*3];
   for(int i=0;i<nWidth*nHeight;i++)
   {
    tmpByte[i*3+0] = lpData[i*4+2];
    tmpByte[i*3+1] = lpData[i*4+1];
    tmpByte[i*3+2] = lpData[i*4+0];
   }
  }
  else
  {
   tmpByte=new byte[nWidth*nHeight*4];
   for(int i=0;i<nWidth*nHeight;i++)
   {
    tmpByte[i*4+0] = lpData[i*4+2];
    tmpByte[i*4+1] = lpData[i*4+1];
    tmpByte[i*4+2] = lpData[i*4+0];
    if( tmpByte[i*4+0] == 0x00 && tmpByte[i*4+1] == 0x00 && tmpByte[i*4+2] == 0x00 )
     tmpByte[i*4+3]=0;
    else
     tmpByte[i*4+3]=255;
   }
  }
  
  bfr.Write(&nWidth,sizeof(int));
  bfr.Write(&nHeight,sizeof(int));
  bfr.Write(&m_bBlend,sizeof(BOOL));
  if(m_bBlend)
   bfr.Write(tmpByte,nWidth*nHeight*4);
  else
   bfr.Write(tmpByte,nWidth*nHeight*3);
  bfr.Close();
  delete tmpByte;

 }
 /
 GlobalFreePtr(lpData);
 return TRUE;
}

int CEditImage::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CEdit::OnCreate(lpCreateStruct) == -1)
  return -1;
 
 // TODO: Add your specialized creation code here
 
 return 0;
}

void CEditImage::OnSize(UINT nType, int cx, int cy)
{
 CEdit::OnSize(nType, cx, cy);
 
 // TODO: Add your message handler code here
 if(m_pDC)
  delete m_pDC;
 m_pDC=new CClientDC(this);
 if(m_pMemDC)
  delete m_pMemDC;
 m_pMemDC=new CDC;
 m_pMemDC->CreateCompatibleDC(m_pDC);
 
 if(m_pBitmap)
 {
  m_pBitmap->DeleteObject();
  delete m_pBitmap;
  m_pBitmap=NULL;
 }
 m_pBitmap=new CBitmap;
 m_pBitmap->CreateCompatibleBitmap(m_pDC,cx,cy);
}
BOOL CEditImage::WriteToRGB(CString sOriginName,CString sDestName,COLORREF clr,CRect rect,CString sNote)
{
 m_clrText=clr;
 m_rect.CopyRect(&rect);
 m_sNote=sNote;
 Convert(sOriginName);
 return SaveBMPByDC(sDestName);
}
void CEditImage::Convert(CString sFileName)
{
 CString strName = sFileName;
 strName = strName.Left(strName.Find('.'));
 //读RGB文件
 CFile fl;
 if(!fl.Open(strName+".RGB",CFile::modeRead))return;

 int iWidth,iHeight;
 
 fl.Read(&iWidth,sizeof(int));
 fl.Read(&iHeight,sizeof(int));
 fl.Read(&m_bBlend,sizeof(BOOL));
 
 if(m_pRGB) delete m_pRGB;

 if(m_bBlend)
 {
  m_pRGB = new BYTE[iWidth*iHeight*4];
  fl.Read(m_pRGB,iWidth*iHeight*4);
  RGBtoBMP(m_pRGB,4,iWidth*iHeight);
 }
 else
 {
  m_pRGB = new BYTE[iWidth*iHeight*3];
  fl.Read(m_pRGB,iWidth*iHeight*3);
  RGBtoBMP(m_pRGB,3,iWidth*iHeight);
 }
 fl.Close();
 //写BMP文件

 BITMAPFILEHEADER pFileHeader;
    pFileHeader.bfType = 0x4d42;
    pFileHeader.bfSize = sizeof(BITMAPFILEHEADER);
    pFileHeader.bfReserved1 = 0;
    pFileHeader.bfReserved2 = 0;
    pFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 //
 BITMAPINFOHEADER bmi;
 bmi.biSize = sizeof(BITMAPINFOHEADER);
 bmi.biWidth = iWidth;
 bmi.biHeight = iHeight;
 bmi.biPlanes = 1;
 bmi.biBitCount = 24;
 bmi.biCompression = BI_RGB;
 bmi.biSizeImage = 0;
 bmi.biXPelsPerMeter = 0;
 bmi.biYPelsPerMeter = 0;
 bmi.biClrUsed = 0;
 bmi.biClrImportant = 0;

 fl.Open(strName+".BMP",CFile::modeCreate | CFile::modeWrite);
 fl.Write(&pFileHeader,sizeof(BITMAPFILEHEADER));
 fl.Write(&bmi,sizeof(BITMAPINFOHEADER));
 fl.Write(m_pRGB,iWidth*iHeight*3);
 fl.Close();
 
 SetImage(strName+".BMP");
 OnPaint();
}
void CEditImage::RGBtoBMP(BYTE* pRGB,int nType,int nNum)
{
    BYTE* pBmp = new BYTE[nNum*3];

 for(int i = 0;i < nNum;i++)
 {
  pBmp[i*3+2] = pRGB[i*nType+0];
  pBmp[i*3+1] = pRGB[i*nType+1];
  pBmp[i*3+0] = pRGB[i*nType+2];
 }
 
 memcpy(pRGB,pBmp,nNum*3*sizeof(BYTE));
 delete pBmp;
}
说明:
此类的基类是一个CEdit,为的是利用它的窗口句柄生成位图并显示保存。
调用方法:
初始化RGB写编号/
 m_pTexManage->m_ctrlEditImage->Create(WS_CHILD|WS_VISIBLE,CRect(0,0,10,10),this,ID_EDIT_WRITERGB);
 m_pTexManage->m_ctrlEditImage->ShowWindow(SW_HIDE);
 

m_pTexManage->m_ctrlEditImage->WriteToRGB(Origin.RGB",sDest,RGB(r,g,b),CRect(0,0,100,50),”Hello”);
参数说明:源文件,目标文件,字体颜色,字体左上角位置,字体宽度,高度,文本 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值