Texture.cpp
Upload User: hcfgz168
Upload Date: 2011-09-11
Package Size: 116k
Code Size: 27k
Category:

OpenGL program

Development Platform:

WINDOWS

  1. //********************************************
  2. // Texture.cpp
  3. //********************************************
  4. // class CTexture
  5. //********************************************
  6. // pierre.alliez@cnet.francetelecom.fr
  7. // Created : 17/12/97
  8. // Modified : 19/12/97
  9. //********************************************
  10. #include "stdafx.h"
  11. #include "math.h"
  12. #include "Texture.h"
  13. //////////////////////////////////////////////
  14. // CONSTRUCTORS
  15. //////////////////////////////////////////////
  16. //********************************************
  17. // Constructor
  18. //********************************************
  19. CTexture::CTexture()
  20. {
  21. m_pData = NULL;
  22. m_Width = 0;
  23. m_WidthByte32 = 0;
  24. m_Height = 0;
  25. m_Depth = 0;
  26. m_FileName = _T("");
  27. }
  28. //********************************************
  29. // Destructor
  30. //********************************************
  31. CTexture::~CTexture()
  32. {
  33. Free();
  34. }
  35. //////////////////////////////////////////////
  36. // DATAS
  37. //////////////////////////////////////////////
  38. //********************************************
  39. // Alloc
  40. //********************************************
  41. int CTexture::Alloc(unsigned int width,
  42. unsigned int height,
  43. unsigned int depth)
  44. {
  45. Free();
  46. unsigned int BytePerPixel = (unsigned int)(depth / 8);
  47. unsigned int Width32 = WidthByte32(width,depth);
  48. // Only rgb and rgba modes
  49. ASSERT(BytePerPixel == 3 || 
  50.      BytePerPixel == 4);
  51. m_pData = new unsigned char [Width32 * height];
  52. if(m_pData == NULL)
  53. {
  54. TRACE("CTexture::Alloc : Insuffisant memoryn");
  55. AfxMessageBox("CTexture::Alloc : Insufisant memory");
  56. return 0;
  57. }
  58. // Set members variables
  59. m_Width = width;
  60. m_WidthByte32 = Width32;
  61. m_Height = height;
  62. m_Depth = depth;
  63. UpdateHeader();
  64. return 1;
  65. }
  66. //********************************************
  67. // Free
  68. //********************************************
  69. void CTexture::Free()
  70. {
  71. if(m_pData != NULL)
  72. {
  73. delete [] m_pData;
  74. m_pData = NULL;
  75. }
  76. m_Width = 0;
  77. m_Height = 0;
  78. m_Depth = 0;
  79. }
  80. //////////////////////////////////////////////
  81. //////////////////////////////////////////////
  82. // FILE READING
  83. //////////////////////////////////////////////
  84. //////////////////////////////////////////////
  85. //********************************************
  86. // ReadFile
  87. // Redirection
  88. //********************************************
  89. int CTexture::ReadFile(char *filename,
  90.  unsigned int width,
  91.  unsigned int height,
  92.  unsigned int depth)
  93. {
  94. // Cleanup
  95. Free();
  96. // Storage
  97. m_FileName = filename;
  98. // Extension
  99. CString string = filename;
  100. string.MakeLower();
  101. TRACE("CTexture::ReadFile : file : %sn",filename);
  102. CString extension = string.Right(4);
  103. // Redirection BMP
  104. if(extension == ".bmp")
  105. return ReadFileBMP(filename);
  106. // Redirection RAW
  107. if(extension == ".raw")
  108. return ReadFileRAW(filename,width,height,depth);
  109. // Unrecognized file format
  110. CString message;
  111. message.Format("CTexture::ReadFile : invalid file redirection : %sn",filename);
  112. AfxMessageBox(string);
  113. return 0;
  114. }
  115. //********************************************
  116. // ReadFileBMP (*.bmp)
  117. //********************************************
  118. // Read windows bmp files
  119. // Accept only 24 bits
  120. // Size : 2^n x 2^m
  121. //********************************************
  122. int CTexture::ReadFileBMP(char *filename)
  123. {
  124. // Check for valid bmp file
  125. CFile file;
  126. CFileException ex;
  127. // Try to open file
  128. if(!file.Open(filename, CFile::modeRead | CFile::typeBinary,&ex))
  129. {
  130. #ifdef _DEBUG
  131.   afxDump << "File could not be opened " << ex.m_cause << "n";
  132. #endif
  133. AfxMessageBox("Unable to open file for reading");
  134. return 0;
  135. }
  136. // File header
  137. BITMAPFILEHEADER FileHeader;
  138. TRY
  139. {
  140. file.Read(&FileHeader,sizeof(BITMAPFILEHEADER));
  141. }
  142. CATCH(CFileException, e)
  143. {
  144. #ifdef _DEBUG
  145. afxDump << "Error during reading " << e->m_cause << "n";
  146. #endif
  147. AfxMessageBox("Error during reading file header");
  148. file.Close();
  149. return 0;
  150. }
  151. END_CATCH
  152. TRACE("FileHeader.bfType : %dn",FileHeader.bfType);
  153. TRACE("FileHeader.bfSize : %dn",FileHeader.bfSize);
  154. TRACE("FileHeader.bfReserved1 : %dn",FileHeader.bfReserved1);
  155. TRACE("FileHeader.bfReserved2 : %dn",FileHeader.bfReserved2);
  156. TRACE("FileHeader.bfOffBits : %dn",FileHeader.bfOffBits);
  157. // Is it a Windows BMP file ? (BM)
  158.   WORD sign = ((WORD) ('M' << 8) | 'B');
  159. if(FileHeader.bfType != sign)
  160. {
  161. AfxMessageBox("Invalid BMP file");
  162. file.Close();
  163. return 0;
  164. }
  165. // Image header
  166. TRY
  167. {
  168. file.Read(&m_Header,sizeof(BITMAPINFOHEADER));
  169. }
  170. CATCH(CFileException, e)
  171. {
  172. #ifdef _DEBUG
  173. afxDump << "Error during reading " << e->m_cause << "n";
  174. #endif
  175. AfxMessageBox("Error during reading image header");
  176. file.Close();
  177. return 0;
  178. }
  179. END_CATCH
  180. // DEBUG
  181. TRACE("n");
  182. TRACE("IMAGE HEADER :n");
  183. TRACE("biSize : %dn",m_Header.biSize);
  184. TRACE("biWidth : %dn",m_Header.biWidth);
  185. TRACE("biHeight : %dn",m_Header.biHeight);
  186. TRACE("biPlanes : %dn",m_Header.biPlanes);
  187. TRACE("biBitCount : %dn",m_Header.biBitCount);
  188. TRACE("biCompression : %dn",m_Header.biCompression);
  189. TRACE("biSizeImage : %dn",m_Header.biSizeImage);
  190. TRACE("biXPelsPerMeter : %dn",m_Header.biXPelsPerMeter);
  191. TRACE("biYPelsPerMeter : %dn",m_Header.biYPelsPerMeter);
  192. TRACE("biClrUsed : %dn",m_Header.biClrUsed);
  193. TRACE("biClrImportant : %dn",m_Header.biClrImportant);
  194. // 24 bits ?
  195. if(m_Header.biPlanes != 1 ||
  196.  m_Header.biBitCount != 24)
  197. {
  198. AfxMessageBox("Texture file must have 24 bits depth");
  199. file.Close();
  200. return 0;
  201. }
  202. // Alloc (does call Free before)
  203. Free();
  204. m_pData = new unsigned char[m_Header.biSizeImage];
  205. if(m_pData == NULL)
  206. {
  207. AfxMessageBox("Insuffisant memory");
  208. file.Close();
  209. return 0;
  210. }
  211. // Update datas
  212. m_Width = m_Header.biWidth;
  213. m_Height = m_Header.biHeight;
  214. m_Depth = m_Header.biBitCount;
  215. // Image reading
  216. TRY
  217. {
  218. file.Read(m_pData,m_Header.biSizeImage);
  219. }
  220. CATCH(CFileException, e)
  221. {
  222. #ifdef _DEBUG
  223. afxDump << "Error during reading " << e->m_cause << "n";
  224. #endif
  225. AfxMessageBox("Error during reading image");
  226. file.Close();
  227. return 0;
  228. }
  229. END_CATCH
  230. // Close file
  231.   file.Close();
  232. // Success, also set FileName
  233. m_FileName = filename;
  234. UpdateWidthByte32();
  235. return 1;
  236. }
  237. //********************************************
  238. // UpdateWidthByte32
  239. //********************************************
  240. void CTexture::UpdateWidthByte32()
  241. {
  242. m_WidthByte32 = WidthByte32(m_Width,m_Depth);
  243. }
  244. //********************************************
  245. // WidthByte32
  246. //********************************************
  247. unsigned int CTexture::WidthByte32(unsigned int width,
  248.  unsigned int depth)
  249. {
  250. // 32 bits alignment (4 bytes)
  251. int rest=(width*depth/8)%4;
  252. if(rest != 0)
  253. return (width*depth/8 + 4-rest);
  254. else
  255. return (width*depth/8);
  256. }
  257. //********************************************
  258. // UpdateHeader
  259. //********************************************
  260. void CTexture::UpdateHeader()
  261. {
  262. UpdateWidthByte32();
  263. m_Header.biWidth = m_Width;
  264. m_Header.biHeight = m_Height;
  265. m_Header.biSizeImage = m_WidthByte32 * m_Height;
  266. m_Header.biSize = 40;
  267. m_Header.biPlanes = 1;
  268. m_Header.biBitCount = m_Depth;
  269. m_Header.biCompression = 0;
  270. m_Header.biXPelsPerMeter = 0;
  271. m_Header.biYPelsPerMeter = 0;
  272. m_Header.biClrUsed = 0;
  273. m_Header.biClrImportant = 0;
  274. }
  275. //********************************************
  276. // ReadFileRAW (*.raw)
  277. //********************************************
  278. // Read raw files
  279. // Accept only 24 or 32 bits
  280. // Size : 2^n x 2^m
  281. //********************************************
  282. int CTexture::ReadFileRAW(char *filename,
  283. unsigned int width,
  284. unsigned int height,
  285. unsigned int depth)
  286. {
  287. ASSERT(width>0);
  288. ASSERT(height>0);
  289. ASSERT(depth>0);
  290. ASSERT(depth%8==0);
  291. ASSERT(depth/8==3 || depth/8==4);
  292. // Check for valid file
  293. CFile file;
  294. CFileException ex;
  295. // Try to open file
  296. if(!file.Open(filename, CFile::modeRead | CFile::typeBinary,&ex))
  297. {
  298. #ifdef _DEBUG
  299.   afxDump << "File could not be opened " << ex.m_cause << "n";
  300. #endif
  301. AfxMessageBox("Unable to open file for reading");
  302. return 0;
  303. }
  304. // Alloc (does call Free before)
  305. if(!Alloc(width,height,depth))
  306. {
  307. AfxMessageBox("Insuffisant memory");
  308. file.Close();
  309. return 0;
  310. }
  311. // Image reading
  312. TRY
  313. {
  314. file.Read(m_pData,m_Width*m_Height*depth/8);
  315. }
  316. CATCH(CFileException, e)
  317. {
  318. #ifdef _DEBUG
  319. afxDump << "Error during reading " << e->m_cause << "n";
  320. #endif
  321. AfxMessageBox("Error during reading image");
  322. file.Close();
  323. return 0;
  324. }
  325. END_CATCH
  326. // Close file
  327.   file.Close();
  328. // Success, also set FileName
  329. m_FileName = filename;
  330. return 1;
  331. }
  332. //////////////////////////////////////////////
  333. //////////////////////////////////////////////
  334. // FILE SAVING
  335. //////////////////////////////////////////////
  336. //////////////////////////////////////////////
  337. //********************************************
  338. // SaveFile
  339. // Redirection
  340. //********************************************
  341. int CTexture::SaveFile(char *filename)
  342. {
  343. CString string = filename;
  344. string.MakeLower();
  345. TRACE("CTexture::SaveFile : file : %sn",filename);
  346. CString extension = string.Right(4);
  347. // Redirection RAW
  348. if(extension == ".raw")
  349. return SaveFileRAW(filename);
  350. // Redirection BMP
  351. if(extension == ".bmp")
  352. return SaveFileBMP(filename);
  353. // Unrecognized file format
  354. CString message;
  355. message.Format("CTexture::SaveFile : invalid file redirection : %sn",filename);
  356. AfxMessageBox(message);
  357. return 0;
  358. }
  359. //********************************************
  360. // SaveFileRAW
  361. //********************************************
  362. int CTexture::SaveFileRAW(char *filename)
  363. {
  364. // Check for valid image
  365. if((m_Width * m_Height * m_Depth) == 0)
  366. {
  367. AfxMessageBox("CTexture::SaveFileRAW : invalid image");
  368. return 0;
  369. }
  370. // Check for valid file
  371. CFile file;
  372. CFileException ex;
  373. // Try to open file
  374. if(!file.Open(filename, CFile::modeWrite | CFile::typeBinary,&ex))
  375. {
  376. #ifdef _DEBUG
  377.   afxDump << "File could not be opened " << ex.m_cause << "n";
  378. #endif
  379. AfxMessageBox("Unable to open file for writing");
  380. return 0;
  381. }
  382. // Image writing
  383. TRY
  384. {
  385. file.Write(m_pData,m_Width*m_Height*m_Depth/8);
  386. }
  387. CATCH(CFileException, e)
  388. {
  389. #ifdef _DEBUG
  390. afxDump << "Error during writing " << e->m_cause << "n";
  391. #endif
  392. AfxMessageBox("Error during writing image");
  393. file.Close();
  394. return 0;
  395. }
  396. END_CATCH
  397. // Close file
  398.   file.Close();
  399. return 1;
  400. }
  401. //********************************************
  402. // SaveFileBMP (*.bmp)
  403. //********************************************
  404. // Save windows bmp files
  405. // Accept only 24 bits
  406. //********************************************
  407. int CTexture::SaveFileBMP(char *filename)
  408. {
  409. if(!IsValid())
  410. return 0;
  411. if(m_Depth != 24)
  412. return 0;
  413. // Check for valid bmp file
  414. CFile file;
  415. CFileException ex;
  416. // Try to open file
  417. if(!file.Open(filename,CFile::modeCreate | CFile::modeWrite | CFile::typeBinary,&ex))
  418. {
  419. #ifdef _DEBUG
  420.   afxDump << "File could not be opened " << ex.m_cause << "n";
  421. #endif
  422. AfxMessageBox("Unable to open file for writing");
  423. return 0;
  424. }
  425. // File header
  426. BITMAPFILEHEADER FileHeader;
  427.   WORD sign = ((WORD) ('M' << 8) | 'B');
  428. FileHeader.bfType = sign;
  429.   FileHeader.bfSize = 14 + 40 + m_WidthByte32*m_Height; 
  430.   FileHeader.bfReserved1 = 0; 
  431.   FileHeader.bfReserved2 = 0; 
  432.   FileHeader.bfOffBits = 54; 
  433. TRACE("nSave BMP File...n");
  434. TRACE("FileHeader.bfType : %dn",FileHeader.bfType);
  435. TRACE("FileHeader.bfSize : %dn",FileHeader.bfSize);
  436. TRACE("FileHeader.bfReserved1 : %dn",FileHeader.bfReserved1);
  437. TRACE("FileHeader.bfReserved2 : %dn",FileHeader.bfReserved2);
  438. TRACE("FileHeader.bfOffBits : %dn",FileHeader.bfOffBits);
  439. TRY
  440. {
  441. file.Write(&FileHeader,sizeof(BITMAPFILEHEADER));
  442. }
  443. CATCH(CFileException, e)
  444. {
  445. #ifdef _DEBUG
  446. afxDump << "Error during writing " << e->m_cause << "n";
  447. #endif
  448. AfxMessageBox("Error during writing file header");
  449. file.Close();
  450. return 0;
  451. }
  452. END_CATCH
  453. // Image header
  454. TRY
  455. {
  456. file.Write(&m_Header,sizeof(BITMAPINFOHEADER));
  457. }
  458. CATCH(CFileException, e)
  459. {
  460. #ifdef _DEBUG
  461. afxDump << "Error during writing " << e->m_cause << "n";
  462. #endif
  463. AfxMessageBox("Error during writing image header");
  464. file.Close();
  465. return 0;
  466. }
  467. END_CATCH
  468. // DEBUG
  469. TRACE("n");
  470. TRACE("IMAGE HEADER :n");
  471. TRACE("biSize : %dn",m_Header.biSize);
  472. TRACE("biWidth : %dn",m_Header.biWidth);
  473. TRACE("biHeight : %dn",m_Header.biHeight);
  474. TRACE("biPlanes : %dn",m_Header.biPlanes);
  475. TRACE("biBitCount : %dn",m_Header.biBitCount);
  476. TRACE("biCompression : %dn",m_Header.biCompression);
  477. TRACE("biSizeImage : %dn",m_Header.biSizeImage);
  478. TRACE("biXPelsPerMeter : %dn",m_Header.biXPelsPerMeter);
  479. TRACE("biYPelsPerMeter : %dn",m_Header.biYPelsPerMeter);
  480. TRACE("biClrUsed : %dn",m_Header.biClrUsed);
  481. TRACE("biClrImportant : %dn",m_Header.biClrImportant);
  482. // Image writing
  483. TRY
  484. {
  485. file.Write(m_pData,m_Header.biSizeImage);
  486. }
  487. CATCH(CFileException, e)
  488. {
  489. #ifdef _DEBUG
  490. afxDump << "Error during writing " << e->m_cause << "n";
  491. #endif
  492. AfxMessageBox("Error during writing image");
  493. file.Close();
  494. return 0;
  495. }
  496. END_CATCH
  497. // Close file
  498.   file.Close();
  499. return 1;
  500. }
  501. //////////////////////////////////////////////
  502. //////////////////////////////////////////////
  503. // CHECKING
  504. //////////////////////////////////////////////
  505. //////////////////////////////////////////////
  506. //********************************************
  507. // IsValid
  508. //********************************************
  509. int CTexture::IsValid()
  510. {
  511. int success = 0;
  512. success = (m_Depth == 24) || (m_Depth == 32);
  513. success &= (m_Width != 0);
  514. success &= (m_Height != 0);
  515. success &= (m_pData != NULL);
  516. if(!success)
  517. {
  518. TRACE("n");
  519. TRACE("Invalid texturen");
  520. TRACE("Width  : %dn",m_Width);
  521. TRACE("Height : %dn",m_Height);
  522. TRACE("Depth  : %dn",m_Depth);
  523. TRACE("Data   : %xn",m_pData);
  524. }
  525. return success;
  526. }
  527. //********************************************
  528. // HigherPowerOfTwo
  529. //********************************************
  530. int CTexture::HigherPowerOfTwo(int value)
  531. {
  532. ASSERT(value > 0);
  533. if(value <= 0)
  534. return value;
  535. int power = 1;
  536. int x = 0;
  537. while(1)
  538. {
  539. x = (int)pow(2,power);
  540. if(x >= value)
  541. return x;
  542. power++;
  543. }
  544. return value;
  545. }
  546. //********************************************
  547. // LowerPowerOfTwo
  548. //********************************************
  549. int CTexture::LowerPowerOfTwo(int value)
  550. {
  551. ASSERT(value > 0);
  552. if(value <= 0)
  553. return value;
  554. int power = 1;
  555. int x = 0;
  556. while(1)
  557. {
  558. x = (int)pow(2,power);
  559. if(x >= value)
  560. return (int)pow(2,power-1);
  561. power++;
  562. }
  563. return value;
  564. }
  565. //********************************************
  566. // SameSize
  567. //********************************************
  568. int CTexture::SameSize(CTexture *pTexture)
  569. {
  570. int success = (m_Width == pTexture->GetWidth());
  571. success &= (m_Height == pTexture->GetHeight());
  572. return success;
  573. }
  574. //********************************************
  575. // Flip BGR to RGB
  576. //********************************************
  577. int CTexture::BGRtoRGB(void)
  578. {
  579. if(!IsValid())
  580. return 0;
  581. unsigned char pixel;
  582. int BytePerPixel = m_Depth/8;
  583. for(unsigned int j=0;j<m_Height;j++)
  584. for(unsigned int i=0;i<m_Width;i++)
  585. {
  586. pixel = m_pData[m_WidthByte32*j+i*BytePerPixel+2];
  587. m_pData[m_WidthByte32*j+i*BytePerPixel+2] = m_pData[m_WidthByte32*j+i*BytePerPixel];
  588. m_pData[m_WidthByte32*j+i*BytePerPixel] = pixel;
  589. }
  590. return 1;
  591. }
  592. //////////////////////////////////////////////
  593. //////////////////////////////////////////////
  594. // DUPLICATE
  595. //////////////////////////////////////////////
  596. //////////////////////////////////////////////
  597. //********************************************
  598. // Extract
  599. //********************************************
  600. int CTexture::Extract(int left,
  601. int top,
  602. int right,
  603. int bottom)
  604. {
  605. ASSERT(IsValid());
  606. // Saturate
  607. if(right == -1)
  608. right = m_Width-1;
  609. if(bottom == -1)
  610. bottom = m_Height-1;
  611. // Check
  612. if(left >= right || top >= bottom)
  613. return 0;
  614. if(left < 0  || left >= (int)m_Width || 
  615.  right < 0 || right >= (int)m_Width)
  616. return 0;
  617. if(top < 0  || top >= (int)m_Height || 
  618.  bottom < 0 || bottom >= (int)m_Height)
  619. return 0;
  620. int NewWidth = right-left+1;
  621. int NewWidthByte32 = WidthByte32(NewWidth,m_Depth);
  622. int NewHeight = bottom-top+1;
  623. int BytePerPixel = m_Depth / 8;
  624. int i,j,k;
  625. TRACE("Start extracting...n");
  626. TRACE("New width : %dn",NewWidth);
  627. TRACE("New height : %dn",NewHeight);
  628. ASSERT(NewWidth>=1);
  629. ASSERT(NewHeight>=1);
  630. // Alloc
  631. unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight];
  632. if(pData == NULL)
  633. {
  634. AfxMessageBox("Insuffisant memeory");
  635. return 0;
  636. }
  637. for(j=0;j<NewHeight;j++)
  638. for(i=0;i<NewWidth;i++)
  639. for(k=0;k<BytePerPixel;k++)
  640. pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(m_Height-1-(j+top))+(i+left)*BytePerPixel+k];
  641. // Replace datas
  642. delete [] m_pData;
  643. m_pData = pData;
  644. m_Width = NewWidth;
  645. m_WidthByte32 = NewWidthByte32;
  646. m_Height = NewHeight;
  647. UpdateHeader();
  648. return 1;
  649. }
  650. //********************************************
  651. // DuplicateMirror
  652. //********************************************
  653. int CTexture::DuplicateMirror(int left,
  654. int top,
  655. int right,
  656. int bottom)
  657. {
  658. if(!Extract(left,top,right,bottom))
  659. return 0;
  660. left = 0;
  661. right = m_Width-1;
  662. top = 0;
  663. bottom = m_Height-1;
  664. int NewWidth = 2*m_Width;
  665. int NewWidthByte32 = WidthByte32(NewWidth,m_Depth);
  666. int NewHeight = 2*m_Height;
  667. int BytePerPixel = m_Depth / 8;
  668. int i,j,k;
  669. TRACE("Start duplicate mirror...n");
  670. TRACE("New width : %dn",NewWidth);
  671. TRACE("New widthbyte32 : %dn",NewWidthByte32);
  672. TRACE("New height : %dn",NewHeight);
  673. ASSERT(NewWidth>=1);
  674. ASSERT(NewHeight>=1);
  675. // Alloc
  676. unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight];
  677. if(pData == NULL)
  678. {
  679. AfxMessageBox("Insuffisant memeory");
  680. return 0;
  681. }
  682. // o o
  683. // x o
  684. for(j=0;j<NewHeight/2;j++)
  685. for(i=0;i<NewWidth/2;i++)
  686. for(k=0;k<BytePerPixel;k++)
  687. pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(i+left)*BytePerPixel+k];
  688. // o o
  689. // o x
  690. for(j=0;j<NewHeight/2;j++)
  691. for(i=NewWidth/2;i<NewWidth;i++)
  692. for(k=0;k<BytePerPixel;k++)
  693. pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(right-(i-NewWidth/2+left))*BytePerPixel+k];
  694. // x o
  695. // o o
  696. for(j=NewHeight/2;j<NewHeight;j++)
  697. for(i=0;i<NewWidth/2;i++)
  698. for(k=0;k<BytePerPixel;k++)
  699. pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(j-NewHeight/2+top)+(i+left)*BytePerPixel+k];
  700. // o x
  701. // o o
  702. for(j=NewHeight/2;j<NewHeight;j++)
  703. for(i=NewWidth/2;i<NewWidth;i++)
  704. for(k=0;k<BytePerPixel;k++)
  705. pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(j-NewHeight/2+top)+(right-(i-NewWidth/2+left))*BytePerPixel+k];
  706. // Replace datas
  707. delete [] m_pData;
  708. m_pData = pData;
  709. m_Width = NewWidth;
  710. m_WidthByte32 = NewWidthByte32;
  711. m_Height = NewHeight;
  712. UpdateHeader();
  713. return 1;
  714. }
  715. //********************************************
  716. // DuplicateRepeatWidth
  717. //********************************************
  718. int CTexture::DuplicateRepeatWidth(int left,
  719.  int top,
  720.  int right,
  721.  int bottom)
  722. {
  723. if(!Extract(left,top,right,bottom))
  724. return 0;
  725. left = 0;
  726. right = m_Width-1;
  727. top = 0;
  728. bottom = m_Height-1;
  729. int NewWidth = 2*m_Width;
  730. int NewWidthByte32 = WidthByte32(NewWidth,m_Depth);
  731. int NewHeight = m_Height;
  732. int BytePerPixel = m_Depth / 8;
  733. int i,j,k;
  734. TRACE("Start duplicate mirror...n");
  735. TRACE("New width : %dn",NewWidth);
  736. TRACE("New widthbyte32 : %dn",NewWidthByte32);
  737. TRACE("New height : %dn",NewHeight);
  738. ASSERT(NewWidth>=1);
  739. ASSERT(NewHeight>=1);
  740. // Alloc
  741. unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight];
  742. if(pData == NULL)
  743. {
  744. AfxMessageBox("Insuffisant memeory");
  745. return 0;
  746. }
  747. // x o
  748. for(j=0;j<NewHeight;j++)
  749. for(i=0;i<NewWidth/2;i++)
  750. for(k=0;k<BytePerPixel;k++)
  751. pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(i+left)*BytePerPixel+k];
  752. // o x
  753. for(j=0;j<NewHeight;j++)
  754. for(i=NewWidth/2;i<NewWidth;i++)
  755. for(k=0;k<BytePerPixel;k++)
  756. pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(i-NewWidth/2+left)*BytePerPixel+k];
  757. // Replace datas
  758. delete [] m_pData;
  759. m_pData = pData;
  760. m_Width = NewWidth;
  761. m_WidthByte32 = NewWidthByte32;
  762. m_Height = NewHeight;
  763. UpdateHeader();
  764. return 1;
  765. }
  766. //////////////////////////////////////////////
  767. //////////////////////////////////////////////
  768. // ALPHA
  769. //////////////////////////////////////////////
  770. //////////////////////////////////////////////
  771. //********************************************
  772. // SetAlphaLayer
  773. //********************************************
  774. int CTexture::SetAlphaLayer(unsigned char alpha) // 0 - 255
  775. {
  776. // Check
  777. if(!IsValid())
  778. return 0;
  779. if(m_Depth != 32)
  780. return 0;
  781. // Fill alpha layer 
  782. int size = m_Width * m_Height;
  783. for(int i=0;i<4*size;i+=4)
  784. m_pData[i+3] = alpha;
  785. return 1;
  786. }
  787. //********************************************
  788. // AddAlphaLayer
  789. //********************************************
  790. int CTexture::AddAlphaLayer(unsigned char alpha) // 0 - 255
  791. {
  792. // Check
  793. if(!IsValid())
  794. return 0;
  795. // Has soon alpha
  796. if(HasAlpha())
  797. return SetAlphaLayer(alpha);
  798. // Alloc memory
  799. unsigned char *pData = new unsigned char[4*m_Width*m_Height];
  800. if(pData == NULL)
  801. {
  802. AfxMessageBox("CTexture::AddAlphaLayer : insuffisant memory");
  803. return 0;
  804. }
  805. // Fill new data
  806. int size = m_Width * m_Height;
  807. int BytePerPixel = m_Depth / 8;
  808. ASSERT(size > 0);
  809. for(int i=0;i<size;i++)
  810. {
  811. pData[4*i+0] = m_pData[BytePerPixel*i+0];
  812. pData[4*i+1] = m_pData[BytePerPixel*i+1];
  813. pData[4*i+2] = m_pData[BytePerPixel*i+2];
  814. pData[4*i+3] = alpha;
  815. }
  816. // Set new depth
  817. m_Depth = 32;
  818. // Replace datas
  819. delete [] m_pData;
  820. m_pData = pData;
  821. return 1;
  822. }
  823. //********************************************
  824. // PutAlpha
  825. // From RGB to grey scales, then alpha layer
  826. //********************************************
  827. int CTexture::PutAlpha(CTexture *pTexture) 
  828. {
  829. // Check
  830. if(!IsValid())
  831. return 0;
  832. if(!pTexture->IsValid())
  833. return 0;
  834. if(!SameSize(pTexture))
  835. return 0;
  836. if(!AddAlphaLayer(0))
  837. return 0;
  838. // Fill new data
  839. unsigned char *pData = pTexture->GetData();
  840. int size = m_Width * m_Height;
  841. int BytePerPixel = pTexture->GetDepth() / 8;
  842. ASSERT(size > 0);
  843. for(int i=0;i<size;i++)
  844. m_pData[4*i+3] = (unsigned char)((int)pData[BytePerPixel*i+0]+
  845.                                  (int)pData[BytePerPixel*i+1]+
  846.  (int)pData[BytePerPixel*i+2])/3;
  847. return 1;
  848. }
  849. //////////////////////////////////////////////
  850. //////////////////////////////////////////////
  851. // DISPLAY
  852. //////////////////////////////////////////////
  853. //////////////////////////////////////////////
  854. //********************************************
  855. // Draw
  856. //********************************************
  857. int CTexture::Draw(CDC *pDC,
  858.  int xOffset,
  859.  int yOffset,
  860.  int width,
  861.  int height)
  862. {
  863. // Checking
  864. if(!IsValid())
  865.   return 0;
  866. // Flags
  867. if(width == -1)
  868. width = m_Width;
  869. if(height == -1)
  870. height = m_Height;
  871. // Painting
  872. return SetDIBitsToDevice(pDC->m_hDC,
  873.                        xOffset,
  874.  yOffset,
  875.  width,
  876.  height,
  877.  0,
  878.  0,
  879.  0,
  880.  m_Height,
  881.  GetData(),
  882.  (CONST BITMAPINFO *)&m_Header,
  883.  DIB_RGB_COLORS);
  884. }
  885. //********************************************
  886. // ReadBuffer
  887. //********************************************
  888. int CTexture::ReadBuffer(unsigned char *buffer, 
  889.  int width, 
  890.  int height, 
  891.  int depth)
  892. {
  893. if(buffer == NULL)
  894. return 0;
  895. if(!Alloc(width,height,depth))
  896. return 0;
  897. int BytePerPixel = depth / 8;
  898. for(int j=0;j<height;j++)
  899. for(int i=0;i<width;i++)
  900. for(int k=0;k<BytePerPixel;k++)
  901. {
  902. m_pData[m_WidthByte32*j + i*BytePerPixel+k] = 
  903.   buffer[(width*j+i)*BytePerPixel+k];
  904. //TRACE("pixel : %dn",(int)buffer[(width*j+i)*BytePerPixel+k]);
  905. }
  906. return 1;
  907. }
  908. //********************************************
  909. // ReadBuffer
  910. //********************************************
  911. int CTexture::ReadBuffer(float *buffer, 
  912.  int width, 
  913.  int height, 
  914.  int depth)
  915. {
  916. if(buffer == NULL)
  917. return 0;
  918. if(!Alloc(width,height,depth))
  919. return 0;
  920. int BytePerPixel = depth / 8;
  921. for(int j=0;j<height;j++)
  922. for(int i=0;i<width;i++)
  923. for(int k=0;k<BytePerPixel;k++)
  924. {
  925. ASSERT(buffer[(width*j+i)*BytePerPixel+k] <= 1.0f);
  926. ASSERT(buffer[(width*j+i)*BytePerPixel+k] >= 0.0f);
  927. m_pData[m_WidthByte32*j + i*BytePerPixel+k] = (BYTE)(255.0f * buffer[(width*j+i)*BytePerPixel+k]);
  928. }
  929. return 1;
  930. }
  931. //********************************************
  932. // Grey
  933. //********************************************
  934. int CTexture::Grey(unsigned int x,
  935.  unsigned int y)
  936. {
  937. ASSERT(x<m_Width && x>=0);
  938. ASSERT(y<m_Height && y>=0);
  939. int BytePerPixel = m_Depth / 8;
  940. // Grey scale
  941. if(BytePerPixel == 1)
  942. return (int)m_pData[m_WidthByte32*y + x]; 
  943. else // 24 or 32 bits (alpha layer)
  944. return (int)((int)m_pData[m_WidthByte32*y + x*BytePerPixel+0]+ 
  945.              (int)m_pData[m_WidthByte32*y + x*BytePerPixel+1]+
  946.  (int)m_pData[m_WidthByte32*y + x*BytePerPixel+2])/3;
  947. }
  948. //********************************************
  949. // Color
  950. //********************************************
  951. void CTexture::Color(unsigned int x,
  952.      unsigned int y, 
  953.  unsigned char *pRed,
  954.  unsigned char *pGreen,
  955.  unsigned char *pBlue)
  956. {
  957. ASSERT(x<m_Width && x>=0);
  958. ASSERT(y<m_Height && y>=0);
  959. int BytePerPixel = m_Depth / 8;
  960. // Grey scale
  961. if(BytePerPixel == 1)
  962. {
  963. *pRed = m_pData[m_WidthByte32*y + x]; 
  964. *pGreen = m_pData[m_WidthByte32*y + x]; 
  965. *pBlue = m_pData[m_WidthByte32*y + x]; 
  966. }
  967. else // 24 or 32 bits (alpha layer)
  968. {
  969. *pRed = m_pData[m_WidthByte32*y + x*BytePerPixel]; 
  970. *pGreen = m_pData[m_WidthByte32*y + x*BytePerPixel+1]; 
  971. *pBlue = m_pData[m_WidthByte32*y + x*BytePerPixel+2]; 
  972. }
  973. }
  974. HANDLE CTexture::ExportHandle()
  975. {
  976. HANDLE handle;
  977. TRACE("Export handle...");
  978.   // Process source handle size
  979.   int size = sizeof(BITMAPINFOHEADER) + m_WidthByte32 * m_Height;
  980.   // Alloc memory
  981. TRACE("alloc...");
  982.   handle = (HANDLE)::GlobalAlloc (GHND,size);
  983.   if(handle != NULL)
  984. {
  985. char *pData = (char *) ::GlobalLock((HGLOBAL)handle);
  986. TRACE("lock...");
  987. // Copy header
  988. TRACE("header...");
  989. memcpy(pData,&m_Header,sizeof(BITMAPINFOHEADER));
  990. // Copy datas
  991. TRACE("datas...");
  992. memcpy(pData+sizeof(BITMAPINFOHEADER),m_pData,m_WidthByte32*m_Height);
  993. // Unlock
  994. TRACE("unlock...");
  995. ::GlobalUnlock((HGLOBAL)handle);
  996. }
  997. TRACE("okn");
  998. return handle;
  999. }
  1000. // ** EOF **