Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1591 lines
48 KiB

  1. // Cdib.cpp
  2. //
  3. #include "stdafx.h"
  4. #include "cdib.h"
  5. #include <windowsx.h>
  6. #include <afxadv.h>
  7. #include <io.h>
  8. #include <errno.h>
  9. #include <math.h>
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CDib
  12. IMPLEMENT_DYNAMIC(CDib, CObject)
  13. /**************************************************************************\
  14. * CDib::CDib()
  15. *
  16. * Constructor for CDib class
  17. *
  18. *
  19. * Arguments:
  20. *
  21. * none
  22. *
  23. * Return Value:
  24. *
  25. * none
  26. *
  27. * History:
  28. *
  29. * 2/14/1999 Original Version
  30. *
  31. \**************************************************************************/
  32. CDib::CDib()
  33. {
  34. m_pBMI = NULL;
  35. m_pBits = NULL;
  36. m_pPalette = NULL;
  37. }
  38. /**************************************************************************\
  39. * CDib::~CDib
  40. *
  41. * Destructor for CDib class
  42. *
  43. *
  44. * Arguments:
  45. *
  46. * none
  47. *
  48. * Return Value:
  49. *
  50. * none
  51. *
  52. * History:
  53. *
  54. * 2/14/1999 Original Version
  55. *
  56. \**************************************************************************/
  57. CDib::~CDib()
  58. {
  59. Free();
  60. }
  61. /**************************************************************************\
  62. * CDib::Free()
  63. *
  64. * Cleans the stored DIB from memory
  65. *
  66. *
  67. * Arguments:
  68. *
  69. * none
  70. *
  71. * Return Value:
  72. *
  73. * void
  74. *
  75. * History:
  76. *
  77. * 2/14/1999 Original Version
  78. *
  79. \**************************************************************************/
  80. void CDib::Free()
  81. {
  82. // Make sure all member data that might have been allocated is freed.
  83. if (m_pBits) {
  84. GlobalFreePtr(m_pBits);
  85. m_pBits = NULL;
  86. }
  87. if (m_pBMI) {
  88. GlobalFreePtr(m_pBMI);
  89. m_pBMI = NULL;
  90. }
  91. if (m_pPalette) {
  92. m_pPalette->DeleteObject();
  93. delete m_pPalette;
  94. m_pPalette = NULL;
  95. }
  96. }
  97. /**************************************************************************\
  98. * CDib::Paint()
  99. *
  100. * Draws a DIB to the target DC
  101. *
  102. *
  103. * Arguments:
  104. *
  105. * hDC - Target DC
  106. * lpDCRect - DC window rect
  107. * lpDIBRect - DIB's rect
  108. *
  109. * Return Value:
  110. *
  111. * status
  112. *
  113. * History:
  114. *
  115. * 2/14/1999 Original Version
  116. *
  117. \**************************************************************************/
  118. BOOL CDib::Paint(HDC hDC, LPRECT lpDCRect, LPRECT lpDIBRect) const
  119. {
  120. float lWidthVal = 1;
  121. float lHeightVal = 1;
  122. if (!m_pBMI)
  123. return FALSE;
  124. HPALETTE hPal = NULL; // Our DIB's palette
  125. HPALETTE hOldPal = NULL; // Previous palette
  126. // Get the DIB's palette, then select it into DC
  127. if (m_pPalette != NULL) {
  128. hPal = (HPALETTE) m_pPalette->m_hObject;
  129. // Select as background since we have
  130. // already realized in forground if needed
  131. hOldPal = ::SelectPalette(hDC, hPal, TRUE);
  132. }
  133. // Make sure to use the stretching mode best for color pictures
  134. ::SetStretchBltMode(hDC, COLORONCOLOR);
  135. // Determine whether to call StretchDIBits() or SetDIBitsToDevice()
  136. BOOL bSuccess;
  137. if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
  138. (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
  139. bSuccess = ::SetDIBitsToDevice(hDC, // hDC
  140. lpDCRect->left, // DestX
  141. lpDCRect->top, // DestY
  142. RECTWIDTH(lpDCRect), // nDestWidth
  143. RECTHEIGHT(lpDCRect), // nDestHeight
  144. lpDIBRect->left, // SrcX
  145. (int)Height() - lpDIBRect->top - RECTHEIGHT(lpDIBRect),
  146. // SrcY
  147. 0, // nStartScan
  148. (WORD)Height(), // nNumScans
  149. m_pBits, // lpBits
  150. m_pBMI, // lpBitsInfo
  151. DIB_RGB_COLORS); // wUsage
  152. else {
  153. //Window width becomes smaller than original image width
  154. if (RECTWIDTH(lpDIBRect) > lpDCRect->right - lpDCRect->left) {
  155. lWidthVal = (float)(lpDCRect->right - lpDCRect->left)/RECTWIDTH(lpDIBRect);
  156. }
  157. //Window height becomes smaller than original image height
  158. if (RECTHEIGHT(lpDIBRect) > lpDCRect->bottom - lpDCRect->top) {
  159. lHeightVal = (float)(lpDCRect->bottom - lpDCRect->top)/RECTHEIGHT(lpDIBRect);
  160. }
  161. long ScaledWidth = (int)(RECTWIDTH(lpDIBRect) * min(lWidthVal,lHeightVal));
  162. long ScaledHeight = (int)(RECTHEIGHT(lpDIBRect) * min(lWidthVal,lHeightVal));
  163. bSuccess = ::StretchDIBits(hDC, // hDC
  164. lpDCRect->left, // DestX
  165. lpDCRect->top, // DestY
  166. ScaledWidth, // nDestWidth
  167. ScaledHeight, // nDestHeight
  168. lpDIBRect->left, // SrcX
  169. lpDIBRect->top, // SrcY
  170. RECTWIDTH(lpDIBRect), // wSrcWidth
  171. RECTHEIGHT(lpDIBRect), // wSrcHeight
  172. m_pBits, // lpBits
  173. m_pBMI, // lpBitsInfo
  174. DIB_RGB_COLORS, // wUsage
  175. SRCCOPY); // dwROP
  176. // update outline areas
  177. // Invalidated right side rect
  178. RECT WindowRect;
  179. WindowRect.top = lpDCRect->top;
  180. WindowRect.left = lpDCRect->left + ScaledWidth;
  181. WindowRect.right = lpDCRect->right;
  182. WindowRect.bottom = lpDCRect->bottom;
  183. HBRUSH hBrush = CreateSolidBrush(GetBkColor(hDC));
  184. FillRect(hDC,&WindowRect,hBrush);
  185. // Invalidated bottom rect
  186. WindowRect.top = lpDCRect->top + ScaledHeight;
  187. WindowRect.left = lpDCRect->left;
  188. WindowRect.right = lpDCRect->left + ScaledWidth;
  189. WindowRect.bottom = lpDCRect->bottom;
  190. FillRect(hDC,&WindowRect,hBrush);
  191. DeleteObject(hBrush);
  192. }
  193. // Reselect old palette
  194. if (hOldPal != NULL) {
  195. ::SelectPalette(hDC, hOldPal, TRUE);
  196. }
  197. return bSuccess;
  198. }
  199. /**************************************************************************\
  200. * CDib::CreatePalette()
  201. *
  202. * Creates a valid palette using the current DIB data
  203. *
  204. *
  205. * Arguments:
  206. *
  207. * none
  208. *
  209. * Return Value:
  210. *
  211. * status
  212. *
  213. * History:
  214. *
  215. * 2/14/1999 Original Version
  216. *
  217. \**************************************************************************/
  218. BOOL CDib::CreatePalette()
  219. {
  220. if (!m_pBMI)
  221. return FALSE;
  222. //get the number of colors in the DIB
  223. WORD wNumColors = NumColors();
  224. if (wNumColors != 0) {
  225. // allocate memory block for logical palette
  226. HANDLE hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*wNumColors);
  227. // if not enough memory, clean up and return NULL
  228. if (hLogPal == 0)
  229. return FALSE;
  230. LPLOGPALETTE lpPal = (LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
  231. // set version and number of palette entries
  232. lpPal->palVersion = PALVERSION;
  233. lpPal->palNumEntries = (WORD)wNumColors;
  234. for (int i = 0; i < (int)wNumColors; i++) {
  235. lpPal->palPalEntry[i].peRed = m_pBMI->bmiColors[i].rgbRed;
  236. lpPal->palPalEntry[i].peGreen = m_pBMI->bmiColors[i].rgbGreen;
  237. lpPal->palPalEntry[i].peBlue = m_pBMI->bmiColors[i].rgbBlue;
  238. lpPal->palPalEntry[i].peFlags = 0;
  239. }
  240. // create the palette and get handle to it
  241. if (m_pPalette) {
  242. m_pPalette->DeleteObject();
  243. delete m_pPalette;
  244. }
  245. m_pPalette = new CPalette;
  246. BOOL bResult = m_pPalette->CreatePalette(lpPal);
  247. ::GlobalUnlock((HGLOBAL) hLogPal);
  248. ::GlobalFree((HGLOBAL) hLogPal);
  249. return bResult;
  250. }
  251. return TRUE;
  252. }
  253. /**************************************************************************\
  254. * CDib::Width
  255. *
  256. * Returns DIB's width in pixels
  257. *
  258. *
  259. * Arguments:
  260. *
  261. * none
  262. *
  263. * Return Value:
  264. *
  265. * DWORD
  266. *
  267. * History:
  268. *
  269. * 2/14/1999 Original Version
  270. *
  271. \**************************************************************************/
  272. DWORD CDib::Width() const
  273. {
  274. if (!m_pBMI)
  275. return 0;
  276. return m_pBMI->bmiHeader.biWidth;
  277. }
  278. /**************************************************************************\
  279. * CDib::Height()
  280. *
  281. * Returns DIB's height in pixels
  282. *
  283. *
  284. * Arguments:
  285. *
  286. * none
  287. *
  288. * Return Value:
  289. *
  290. * DWORD
  291. *
  292. * History:
  293. *
  294. * 2/14/1999 Original Version
  295. *
  296. \**************************************************************************/
  297. DWORD CDib::Height() const
  298. {
  299. if (!m_pBMI)
  300. return 0;
  301. return m_pBMI->bmiHeader.biHeight;
  302. }
  303. /**************************************************************************\
  304. * CDib::PaletteSize()
  305. *
  306. * Returns the size of the DIB's palette
  307. *
  308. *
  309. * Arguments:
  310. *
  311. * none
  312. *
  313. * Return Value:
  314. *
  315. * WORD - Palette size in bytes
  316. *
  317. * History:
  318. *
  319. * 2/14/1999 Original Version
  320. *
  321. \**************************************************************************/
  322. WORD CDib::PaletteSize() const
  323. {
  324. if (!m_pBMI)
  325. return 0;
  326. return NumColors() * sizeof(RGBQUAD);
  327. }
  328. /**************************************************************************\
  329. * CDib::NumColors()
  330. *
  331. * Returns the number of colors in DIB's palette
  332. *
  333. *
  334. * Arguments:
  335. *
  336. * none
  337. *
  338. * Return Value:
  339. *
  340. * WORD - Number of colors used
  341. *
  342. * History:
  343. *
  344. * 2/14/1999 Original Version
  345. *
  346. \**************************************************************************/
  347. WORD CDib::NumColors() const
  348. {
  349. if (!m_pBMI)
  350. return 0;
  351. WORD wBitCount; // DIB bit count
  352. // The number of colors in the color table can be less than
  353. // the number of bits per pixel allows for (i.e. lpbi->biClrUsed
  354. // can be set to some value).
  355. // If this is the case, return the appropriate value.
  356. DWORD dwClrUsed;
  357. dwClrUsed = m_pBMI->bmiHeader.biClrUsed;
  358. if (dwClrUsed != 0)
  359. return(WORD)dwClrUsed;
  360. // Calculate the number of colors in the color table based on
  361. // the number of bits per pixel for the DIB.
  362. wBitCount = m_pBMI->bmiHeader.biBitCount;
  363. // return number of colors based on bits per pixel
  364. switch (wBitCount) {
  365. case 1:
  366. return 2;
  367. case 4:
  368. return 16;
  369. case 8:
  370. return 256;
  371. default:
  372. return 0;
  373. }
  374. }
  375. /**************************************************************************\
  376. * CDib::Save()
  377. *
  378. * Saves the DIB to a file.
  379. * note: the CFile must be opened before this call is made!
  380. *
  381. *
  382. * Arguments:
  383. *
  384. * CFile& - Open CFile
  385. *
  386. * Return Value:
  387. *
  388. * DWORD - Number of Bytes saved in the file
  389. *
  390. * History:
  391. *
  392. * 2/14/1999 Original Version
  393. *
  394. \**************************************************************************/
  395. DWORD CDib::Save(CFile& file) const
  396. {
  397. BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
  398. DWORD dwDIBSize;
  399. if (m_pBMI == NULL)
  400. return 0;
  401. // Fill in the fields of the file header
  402. // Fill in file type (first 2 bytes must be "BM" for a bitmap)
  403. bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
  404. // Calculating the size of the DIB is a bit tricky (if we want to
  405. // do it right). The easiest way to do this is to call GlobalSize()
  406. // on our global handle, but since the size of our global memory may have
  407. // been padded a few bytes, we may end up writing out a few too
  408. // many bytes to the file (which may cause problems with some apps).
  409. //
  410. // So, instead let's calculate the size manually (if we can)
  411. //
  412. // First, find size of header plus size of color table. Since the
  413. // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
  414. // the size of the structure, let's use this.
  415. dwDIBSize = *(LPDWORD)&m_pBMI->bmiHeader + PaletteSize(); // Partial Calculation
  416. // Now calculate the size of the image
  417. if ((m_pBMI->bmiHeader.biCompression == BI_RLE8) || (m_pBMI->bmiHeader.biCompression == BI_RLE4)) {
  418. // It's an RLE bitmap, we can't calculate size, so trust the
  419. // biSizeImage field
  420. dwDIBSize += m_pBMI->bmiHeader.biSizeImage;
  421. } else {
  422. DWORD dwBmBitsSize; // Size of Bitmap Bits only
  423. // It's not RLE, so size is Width (DWORD aligned) * Height
  424. dwBmBitsSize = WIDTHBYTES((m_pBMI->bmiHeader.biWidth)*((DWORD)m_pBMI->bmiHeader.biBitCount)) * m_pBMI->bmiHeader.biHeight;
  425. dwDIBSize += dwBmBitsSize;
  426. // Now, since we have calculated the correct size, why don't we
  427. // fill in the biSizeImage field (this will fix any .BMP files which
  428. // have this field incorrect).
  429. m_pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
  430. }
  431. // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
  432. bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  433. bmfHdr.bfReserved1 = 0;
  434. bmfHdr.bfReserved2 = 0;
  435. // Now, calculate the offset the actual bitmap bits will be in
  436. // the file -- It's the Bitmap file header plus the DIB header,
  437. // plus the size of the color table.
  438. bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + m_pBMI->bmiHeader.biSize + PaletteSize();
  439. // Write the file header
  440. file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  441. DWORD dwBytesSaved = sizeof(BITMAPFILEHEADER);
  442. // Write the DIB header
  443. UINT nCount = sizeof(BITMAPINFO) + (NumColors()-1)*sizeof(RGBQUAD);
  444. dwBytesSaved += nCount;
  445. file.Write(m_pBMI, nCount);
  446. // Write the DIB bits
  447. DWORD dwBytes = m_pBMI->bmiHeader.biBitCount * Width();
  448. // Calculate the number of bytes per line
  449. if (dwBytes%32 == 0)
  450. dwBytes /= 8;
  451. else
  452. dwBytes = dwBytes/8 + (32-dwBytes%32)/8 + (((32-dwBytes%32)%8 > 0) ? 1 : 0);
  453. nCount = dwBytes * Height();
  454. dwBytesSaved += nCount;
  455. file.WriteHuge(m_pBits, nCount);
  456. return dwBytesSaved;
  457. }
  458. /**************************************************************************\
  459. * CDib::Read()
  460. *
  461. * Reads from a File into DIB form
  462. * Note: the CFile must be opened before this call is made!
  463. *
  464. * Arguments:
  465. *
  466. * CFile& - Open CFile
  467. * FileType - BMP_IMAGE, TIFF_IMAGE
  468. *
  469. * Return Value:
  470. *
  471. * DWORD - Number of bytes read from the CFile
  472. *
  473. *
  474. * History:
  475. *
  476. * 2/14/1999 Original Version
  477. *
  478. \**************************************************************************/
  479. DWORD CDib::Read(CFile& file,int FileType)
  480. {
  481. DWORD dwReadBytes = 0;
  482. // Ensures no memory leaks will occur
  483. Free();
  484. if (FileType == TIFF_IMAGE) {
  485. DWORD dwCurrentFileOffset = 0;
  486. DWORD dwStripByteCountOffset = 0;
  487. DWORD dwStripOffset = 0;
  488. // TIFF variables
  489. TIFFFILEHEADER tfHeader;
  490. TIFFTAG tTag;
  491. short TagCount = 0;
  492. dwReadBytes = file.Read(&tfHeader,sizeof(TIFFFILEHEADER));
  493. if (dwReadBytes != sizeof(TIFFFILEHEADER)) {
  494. AfxMessageBox("Error reading TIFF file header");
  495. return 0;
  496. }
  497. dwCurrentFileOffset += dwReadBytes;
  498. if (tfHeader.tfType != 42) {
  499. AfxMessageBox("Invalid TIFF format");
  500. return 0;
  501. }
  502. if (tfHeader.tfByteOrder[0] != 'I' && tfHeader.tfByteOrder[1] != 'I') {
  503. AfxMessageBox("Invalid TIFF format not 'II'");
  504. return 0;
  505. }
  506. //
  507. // move file pointer to TAG offset
  508. //
  509. dwCurrentFileOffset = file.Seek(tfHeader.tfOffset,CFile::begin);
  510. dwReadBytes = file.Read(&TagCount,sizeof(short));
  511. if (dwReadBytes != sizeof(short)) {
  512. AfxMessageBox("Error reading Number of TIFF TAGS");
  513. return 0;
  514. }
  515. dwCurrentFileOffset += dwReadBytes;
  516. if (TagCount <=0) {
  517. AfxMessageBox("Number of TIFF TAGS must be 1 or more..");
  518. return 0;
  519. }
  520. TIFFTODIBDATA TiffToDIBData;
  521. long tempOffset = 0;
  522. int ValueCount = 0;
  523. memset(&TiffToDIBData,0,sizeof(TIFFTODIBDATA));
  524. for (int i = 1;i<=TagCount;i++) {
  525. dwReadBytes = file.Read(&tTag,sizeof(TIFFTAG));
  526. if (dwReadBytes != sizeof(TIFFTAG)) {
  527. AfxMessageBox("Error reading TIFF TAGS");
  528. return 0;
  529. }
  530. switch (tTag.ttTag) {
  531. case TIFF_NEWSUBFILETYPE:
  532. break;
  533. case TIFF_IMAGEWIDTH:
  534. TiffToDIBData.bmiHeader.biWidth = tTag.ttOffset;
  535. break;
  536. case TIFF_LENGTH:
  537. TiffToDIBData.bmiHeader.biHeight = tTag.ttOffset;
  538. break;
  539. case TIFF_BITSPERSAMPLE:
  540. if (tTag.ttCount == 3)
  541. TiffToDIBData.bmiHeader.biBitCount = 24;
  542. else
  543. TiffToDIBData.bmiHeader.biBitCount = (unsigned short)tTag.ttOffset;
  544. break;
  545. case TIFF_COMPRESSION:
  546. TiffToDIBData.CompressionType = tTag.ttOffset;
  547. break;
  548. case TIFF_PHOTOINTERP:
  549. break;
  550. case TIFF_IMAGEDESCRIPTION:
  551. tempOffset = dwCurrentFileOffset;
  552. file.Seek(tTag.ttOffset,CFile::begin);
  553. file.Read(TiffToDIBData.Description,sizeof(tTag.ttCount));
  554. file.Seek(tempOffset,CFile::begin);
  555. break;
  556. case TIFF_STRIPOFFSETS:
  557. TiffToDIBData.StripOffsets = tTag.ttOffset;
  558. TiffToDIBData.OffsetCount = tTag.ttCount;
  559. TiffToDIBData.pStripOffsets = (long*)GlobalAlloc(GPTR,sizeof(long) * tTag.ttCount);
  560. if (tTag.ttCount == 1) {
  561. //
  562. // we only have one huge strip
  563. //
  564. TiffToDIBData.pStripOffsets[0] = tTag.ttOffset;
  565. } else {
  566. //
  567. // we have multiple strips
  568. //
  569. tempOffset = dwCurrentFileOffset;
  570. file.Seek(tTag.ttOffset,CFile::begin);
  571. file.Read(TiffToDIBData.pStripOffsets,sizeof(long) * tTag.ttCount);
  572. file.Seek(tempOffset,CFile::begin);
  573. }
  574. break;
  575. case TIFF_ORIENTATION:
  576. break;
  577. case TIFF_SAMPLESPERPIXEL:
  578. break;
  579. case TIFF_ROWSPERSTRIP:
  580. TiffToDIBData.RowsPerStrip = tTag.ttOffset;
  581. break;
  582. case TIFF_STRIPBYTECOUNTS:
  583. TiffToDIBData.StripByteCounts = tTag.ttOffset;
  584. TiffToDIBData.pStripByteCountsOffsets = (long*)GlobalAlloc(GPTR,sizeof(long) * tTag.ttCount);
  585. if (tTag.ttCount == 1) {
  586. //
  587. // we only have one huge strip
  588. //
  589. TiffToDIBData.pStripByteCountsOffsets[0] = tTag.ttOffset;
  590. } else {
  591. //
  592. // we have multiple strips
  593. //
  594. tempOffset = dwCurrentFileOffset;
  595. file.Seek(tTag.ttOffset,CFile::begin);
  596. file.Read(TiffToDIBData.pStripByteCountsOffsets,sizeof(long) * tTag.ttCount);
  597. file.Seek(tempOffset,CFile::begin);
  598. }
  599. break;
  600. case TIFF_XRESOLUTION:
  601. tempOffset = dwCurrentFileOffset;
  602. file.Seek(tTag.ttOffset,CFile::begin);
  603. file.Read(&TiffToDIBData.xResolution,sizeof(TIFFRATIONAL));
  604. file.Seek(tempOffset,CFile::begin);
  605. break;
  606. case TIFF_YRESOLUTION:
  607. tempOffset = dwCurrentFileOffset;
  608. file.Seek(tTag.ttOffset,CFile::begin);
  609. file.Read(&TiffToDIBData.yResolution,sizeof(TIFFRATIONAL));
  610. file.Seek(tempOffset,CFile::begin);
  611. break;
  612. case TIFF_RESOLUTIONUNIT:
  613. TiffToDIBData.ResolutionUnit = tTag.ttOffset;
  614. break;
  615. case TIFF_SOFTWARE:
  616. tempOffset = dwCurrentFileOffset;
  617. file.Seek(tTag.ttOffset,CFile::begin);
  618. file.Read(TiffToDIBData.Software,sizeof(tTag.ttCount));
  619. file.Seek(tempOffset,CFile::begin);
  620. break;
  621. default:
  622. break;
  623. }
  624. dwCurrentFileOffset += dwReadBytes;
  625. }
  626. //
  627. // read next Tagcount to see if there are more TAGS
  628. //
  629. dwReadBytes = file.Read(&TagCount,sizeof(short));
  630. if (dwReadBytes != sizeof(short)) {
  631. AfxMessageBox("Error reading Number of TIFF TAGS");
  632. return 0;
  633. }
  634. //
  635. // if there are more tags exit for now..
  636. //
  637. if (TagCount >0) {
  638. //AfxMessageBox("There are more TIFF TAGS in this file");
  639. //return;
  640. }
  641. //
  642. // calculate the rest of the TiffToDIBData
  643. //
  644. int BytesPerPixel = 0;
  645. //
  646. // 8-bit DATA
  647. //
  648. if (TiffToDIBData.bmiHeader.biBitCount == 8) {
  649. BytesPerPixel = 1;
  650. if (TiffToDIBData.ColorsUsed == 0)
  651. TiffToDIBData.bmiHeader.biClrUsed = 256;
  652. else
  653. TiffToDIBData.bmiHeader.biClrUsed = TiffToDIBData.ColorsUsed;
  654. }
  655. //
  656. // 24-bit DATA
  657. //
  658. else if (TiffToDIBData.bmiHeader.biBitCount == 24) {
  659. BytesPerPixel = 3;
  660. TiffToDIBData.bmiHeader.biClrUsed = 0;
  661. }
  662. //
  663. // 4-bit DATA
  664. //
  665. else if (TiffToDIBData.bmiHeader.biBitCount == 4) {
  666. BytesPerPixel = 2;
  667. TiffToDIBData.bmiHeader.biClrUsed = 256;
  668. }
  669. //
  670. // 1-bit DATA
  671. //
  672. else {
  673. BytesPerPixel = 0;
  674. TiffToDIBData.bmiHeader.biClrUsed = 2;
  675. }
  676. TiffToDIBData.bmiHeader.biSizeImage = WIDTHBYTES((TiffToDIBData.bmiHeader.biWidth)*((DWORD)TiffToDIBData.bmiHeader.biBitCount)) * TiffToDIBData.bmiHeader.biHeight;
  677. TiffToDIBData.bmiHeader.biPlanes = 1;
  678. TiffToDIBData.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  679. //
  680. // create Palette size if one exists
  681. //
  682. RGBQUAD* pPalette = NULL;
  683. long PaletteSize = 0;
  684. if (TiffToDIBData.bmiHeader.biClrUsed != 0) {
  685. PaletteSize = TiffToDIBData.bmiHeader.biClrUsed * sizeof(RGBQUAD);
  686. pPalette = (RGBQUAD*)GlobalAllocPtr(GHND, PaletteSize);
  687. if (pPalette == NULL) {
  688. AfxMessageBox("Failed to Create Palette");
  689. return 0;
  690. }
  691. if (TiffToDIBData.bmiHeader.biBitCount == 8) {
  692. if (TiffToDIBData.ColorsUsed == 0) {
  693. //
  694. // create a grayscale palette
  695. //
  696. for (int i = 0;i<(int)TiffToDIBData.bmiHeader.biClrUsed;i++) {
  697. pPalette[i].rgbRed = (BYTE)i;
  698. pPalette[i].rgbBlue = (BYTE)i;
  699. pPalette[i].rgbGreen = (BYTE)i;
  700. pPalette[i].rgbReserved = 0;
  701. }
  702. } else {
  703. //
  704. // create the color palette from colormap
  705. //
  706. TiffToDIBData.bmiHeader.biClrUsed = TiffToDIBData.ColorsUsed;
  707. }
  708. }
  709. if (TiffToDIBData.bmiHeader.biBitCount == 1) {
  710. //
  711. // create a black and white palette
  712. //
  713. pPalette[0].rgbRed = 0;
  714. pPalette[0].rgbBlue = 0;
  715. pPalette[0].rgbGreen = 0;
  716. pPalette[0].rgbReserved = 0;
  717. pPalette[1].rgbRed = 255;
  718. pPalette[1].rgbBlue = 255;
  719. pPalette[1].rgbGreen = 255;
  720. pPalette[1].rgbReserved = 255;
  721. }
  722. }
  723. BITMAPFILEHEADER bmfHeader;
  724. memset(&bmfHeader,0,sizeof(BITMAPFILEHEADER));
  725. bmfHeader.bfType = DIB_HEADER_MARKER;
  726. bmfHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + PaletteSize + TiffToDIBData.bmiHeader.biSizeImage;
  727. bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ PaletteSize;
  728. // Allocate memory for DIB info header and possible palette
  729. m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER) + (PaletteSize*2));
  730. if (m_pBMI == 0)
  731. return 0;
  732. DWORD dwLength = file.GetLength();
  733. m_pBits = (LPBYTE)GlobalAllocPtr(GHND, TiffToDIBData.bmiHeader.biSizeImage + PaletteSize);
  734. if (m_pBits == 0) {
  735. GlobalFreePtr(m_pBMI);
  736. m_pBMI = NULL;
  737. return 0;
  738. }
  739. BYTE* pData = m_pBits;
  740. //
  741. // set line width (DWORD aligned length)
  742. //
  743. long LineWidth = TiffToDIBData.bmiHeader.biSizeImage/TiffToDIBData.bmiHeader.biHeight;
  744. DWORD ImageByteCount = 0;
  745. for (i = 0;i < TiffToDIBData.OffsetCount;i++) {
  746. //
  747. // seek to strip
  748. //
  749. file.Seek(TiffToDIBData.pStripOffsets[i],CFile::begin);
  750. //
  751. // read strip data (numbytes from pStripBytesCounts.
  752. //
  753. file.ReadHuge(pData,TiffToDIBData.pStripByteCountsOffsets[i]);
  754. pData += TiffToDIBData.pStripByteCountsOffsets[i];
  755. ImageByteCount+= TiffToDIBData.pStripByteCountsOffsets[i];
  756. }
  757. BYTE ColorValue = 0;
  758. int LineCount = 1;
  759. pData = m_pBits;
  760. //
  761. // Swap Red and Blue values if the data is 24-BIT
  762. //
  763. if (TiffToDIBData.bmiHeader.biClrUsed == 0) {
  764. for (LONG i = 0; i < (LONG)TiffToDIBData.bmiHeader.biSizeImage; i += 3) {
  765. BYTE bTemp = pData[i];
  766. pData[i] = pData[i + 2];
  767. pData[i + 2] = bTemp;
  768. }
  769. }
  770. // Write BITMAPINFOHEADER to member
  771. memmove(m_pBMI,&TiffToDIBData.bmiHeader,sizeof(BITMAPINFOHEADER));
  772. if (TiffToDIBData.bmiHeader.biClrUsed >0) {
  773. memmove(m_pBMI->bmiColors,pPalette,PaletteSize);
  774. }
  775. if (TiffToDIBData.bmiHeader.biBitCount == 1)
  776. LineWidth = (long)ceil((float)TiffToDIBData.bmiHeader.biWidth/8.0f);
  777. else
  778. LineWidth = TiffToDIBData.bmiHeader.biWidth * BytesPerPixel;
  779. pData = m_pBits;
  780. //
  781. // check DWORD alignment of data
  782. //
  783. if ((LineWidth % sizeof(DWORD))) {
  784. //
  785. // Pad data
  786. //
  787. int PaddedBytes = sizeof(DWORD) - (LineWidth % sizeof(DWORD));
  788. LineCount = 1;
  789. BYTE* pCurrent = NULL;
  790. BYTE* pDest = NULL;
  791. for (LineCount = TiffToDIBData.bmiHeader.biHeight;LineCount > 1;LineCount--) {
  792. pCurrent = pData + (LineWidth*(LineCount - 1));
  793. pDest = pCurrent + (PaddedBytes*(LineCount - 1));
  794. memmove(pDest,pCurrent,(LineWidth + PaddedBytes));
  795. }
  796. }
  797. if (pPalette)
  798. GlobalFreePtr(pPalette);
  799. if (TiffToDIBData.pStripByteCountsOffsets != NULL)
  800. GlobalFree(TiffToDIBData.pStripByteCountsOffsets);
  801. if (TiffToDIBData.pStripOffsets != NULL)
  802. GlobalFree(TiffToDIBData.pStripOffsets);
  803. //
  804. // flip the data because we are converting it
  805. // to DIB form
  806. //
  807. Flip(m_pBits);
  808. CreatePalette();
  809. } else {
  810. BITMAPFILEHEADER bmfHeader;
  811. // Go read the DIB file header and check if it's valid.
  812. if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
  813. return 0;
  814. if (bmfHeader.bfType != DIB_HEADER_MARKER)
  815. return 0;
  816. dwReadBytes = sizeof(bmfHeader);
  817. // Allocate memory for DIB info header and possible palette
  818. m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER) + 256*sizeof(RGBQUAD));
  819. if (m_pBMI == 0)
  820. return 0;
  821. // Read header.
  822. if (file.Read(m_pBMI, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)) != (UINT)(bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER))) {
  823. GlobalFreePtr(m_pBMI);
  824. m_pBMI = NULL;
  825. return 0;
  826. }
  827. dwReadBytes += bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER);
  828. DWORD dwLength = file.GetLength();
  829. // Go read the bits.
  830. m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwLength - bmfHeader.bfOffBits);
  831. if (m_pBits == 0) {
  832. GlobalFreePtr(m_pBMI);
  833. m_pBMI = NULL;
  834. return 0;
  835. }
  836. if (file.ReadHuge(m_pBits, dwLength-bmfHeader.bfOffBits) != (dwLength - bmfHeader.bfOffBits)) {
  837. GlobalFreePtr(m_pBMI);
  838. m_pBMI = NULL;
  839. GlobalFreePtr(m_pBits);
  840. m_pBits = NULL;
  841. return 0;
  842. }
  843. dwReadBytes += dwLength - bmfHeader.bfOffBits;
  844. CreatePalette();
  845. }
  846. return dwReadBytes;
  847. }
  848. /**************************************************************************\
  849. * CDib::ReadFromHGLOBAL()
  850. *
  851. * Reads a global chunk of memory into DIB form
  852. *
  853. *
  854. * Arguments:
  855. *
  856. * hGlobal - Global block of memory
  857. * FileType - BMP_IMAGE, TIFF_IMAGE
  858. *
  859. * Return Value:
  860. *
  861. * status
  862. *
  863. * History:
  864. *
  865. * 2/14/1999 Original Version
  866. *
  867. \**************************************************************************/
  868. BOOL CDib::ReadFromHGLOBAL(HGLOBAL hGlobal,int FileType)
  869. {
  870. Free();
  871. if (hGlobal == NULL)
  872. return FALSE;
  873. if (FileType == TIFF_IMAGE) {
  874. LPBYTE pSrcDib = (LPBYTE)GlobalLock(hGlobal);
  875. TIFFFILEHEADER* ptfHeader = NULL;
  876. ptfHeader = (TIFFFILEHEADER*)pSrcDib;
  877. LPBYTE pPtr = pSrcDib;
  878. LPBYTE ptempPtr = NULL;
  879. DWORD dwCurrentFileOffset = 0;
  880. DWORD dwStripByteCountOffset = 0;
  881. DWORD dwStripOffset = 0;
  882. // TIFF variables
  883. TIFFTAG tTag;
  884. short TagCount = 0;
  885. if (ptfHeader->tfType != 42) {
  886. AfxMessageBox("Invalid TIFF format");
  887. return 0;
  888. }
  889. if (ptfHeader->tfByteOrder[0] != 'I' && ptfHeader->tfByteOrder[1] != 'I') {
  890. AfxMessageBox("Invalid TIFF format not 'II'");
  891. return 0;
  892. }
  893. //
  894. // move pointer to TAG offset
  895. //
  896. pPtr += ptfHeader->tfOffset;
  897. memmove(&TagCount,pPtr,sizeof(short));
  898. pPtr += sizeof(short);
  899. if (TagCount <=0) {
  900. AfxMessageBox("Number of TIFF TAGS must be 1 or more..");
  901. return 0;
  902. }
  903. TIFFTODIBDATA TiffToDIBData;
  904. long tempOffset = 0;
  905. int ValueCount = 0;
  906. memset(&TiffToDIBData,0,sizeof(TIFFTODIBDATA));
  907. for (int i = 1;i<=TagCount;i++) {
  908. memmove(&tTag,pPtr,sizeof(TIFFTAG));
  909. pPtr += sizeof(TIFFTAG);
  910. switch (tTag.ttTag) {
  911. case TIFF_NEWSUBFILETYPE:
  912. break;
  913. case TIFF_IMAGEWIDTH:
  914. TiffToDIBData.bmiHeader.biWidth = tTag.ttOffset;
  915. break;
  916. case TIFF_LENGTH:
  917. TiffToDIBData.bmiHeader.biHeight = tTag.ttOffset;
  918. break;
  919. case TIFF_BITSPERSAMPLE:
  920. if (tTag.ttCount == 3)
  921. TiffToDIBData.bmiHeader.biBitCount = 24;
  922. else
  923. TiffToDIBData.bmiHeader.biBitCount = (unsigned short)tTag.ttOffset;
  924. break;
  925. case TIFF_COMPRESSION:
  926. TiffToDIBData.CompressionType = tTag.ttOffset;
  927. break;
  928. case TIFF_PHOTOINTERP:
  929. break;
  930. case TIFF_IMAGEDESCRIPTION:
  931. ptempPtr = pPtr; // save current pointer
  932. pPtr = pSrcDib; // move pointer to start of data
  933. pPtr += tTag.ttOffset; // seek to offset
  934. memmove(TiffToDIBData.Description,pPtr,sizeof(tTag.ttCount)); // read data
  935. pPtr = ptempPtr; // move pointer back to org. position
  936. break;
  937. case TIFF_STRIPOFFSETS:
  938. TiffToDIBData.StripOffsets = tTag.ttOffset;
  939. TiffToDIBData.OffsetCount = tTag.ttCount;
  940. TiffToDIBData.pStripOffsets = (long*)GlobalAlloc(GPTR,sizeof(long) * tTag.ttCount);
  941. if (tTag.ttCount == 1) {
  942. //
  943. // we only have one huge strip
  944. //
  945. TiffToDIBData.pStripOffsets[0] = tTag.ttOffset;
  946. } else {
  947. //
  948. // we have multiple strips
  949. //
  950. ptempPtr = pPtr; // save current pointer
  951. pPtr = pSrcDib; // move pointer to start of data
  952. pPtr += tTag.ttOffset; // seek to offset
  953. memmove(TiffToDIBData.pStripOffsets,pPtr,sizeof(long) * tTag.ttCount); // read data
  954. pPtr = ptempPtr; // move pointer back to org. position
  955. }
  956. break;
  957. case TIFF_ORIENTATION:
  958. break;
  959. case TIFF_SAMPLESPERPIXEL:
  960. break;
  961. case TIFF_ROWSPERSTRIP:
  962. TiffToDIBData.RowsPerStrip = tTag.ttOffset;
  963. break;
  964. case TIFF_STRIPBYTECOUNTS:
  965. TiffToDIBData.StripByteCounts = tTag.ttOffset;
  966. TiffToDIBData.pStripByteCountsOffsets = (long*)GlobalAlloc(GPTR,sizeof(long) * tTag.ttCount);
  967. if (tTag.ttCount == 1) {
  968. //
  969. // we only have one huge strip
  970. //
  971. TiffToDIBData.pStripByteCountsOffsets[0] = tTag.ttOffset;
  972. } else {
  973. //
  974. // we have multiple strips
  975. //
  976. ptempPtr = pPtr; // save current pointer
  977. pPtr = pSrcDib; // move pointer to start of data
  978. pPtr += tTag.ttOffset; // seek to offset
  979. memmove(TiffToDIBData.pStripByteCountsOffsets,pPtr,sizeof(long) * tTag.ttCount); // read data
  980. pPtr = ptempPtr; // move pointer back to org. position
  981. }
  982. break;
  983. case TIFF_XRESOLUTION:
  984. ptempPtr = pPtr; // save current pointer
  985. pPtr = pSrcDib; // move pointer to start of data
  986. pPtr += tTag.ttOffset; // seek to offset
  987. memmove(&TiffToDIBData.xResolution,pPtr,sizeof(TIFFRATIONAL)); // read data
  988. pPtr = ptempPtr; // move pointer back to org. position
  989. break;
  990. case TIFF_YRESOLUTION:
  991. ptempPtr = pPtr; // save current pointer
  992. pPtr = pSrcDib; // move pointer to start of data
  993. pPtr += tTag.ttOffset; // seek to offset
  994. memmove(&TiffToDIBData.yResolution,pPtr,sizeof(TIFFRATIONAL)); // read data
  995. pPtr = ptempPtr; // move pointer back to org. position
  996. break;
  997. case TIFF_RESOLUTIONUNIT:
  998. TiffToDIBData.ResolutionUnit = tTag.ttOffset;
  999. break;
  1000. case TIFF_SOFTWARE:
  1001. ptempPtr = pPtr; // save current pointer
  1002. pPtr = pSrcDib; // move pointer to start of data
  1003. pPtr += tTag.ttOffset; // seek to offset
  1004. memmove(TiffToDIBData.Software,pPtr,sizeof(tTag.ttCount)); // read data
  1005. pPtr = ptempPtr; // move pointer back to org. position
  1006. break;
  1007. default:
  1008. break;
  1009. }
  1010. }
  1011. //
  1012. // read next Tagcount to see if there are more TAGS
  1013. //
  1014. //dwReadBytes = file.Read(&TagCount,sizeof(short));
  1015. //if(dwReadBytes != sizeof(short))
  1016. //{
  1017. // AfxMessageBox("Error reading Number of TIFF TAGS");
  1018. // return 0;
  1019. //}
  1020. //
  1021. // if there are more tags exit for now..
  1022. //
  1023. //if(TagCount >0)
  1024. //{
  1025. //AfxMessageBox("There are more TIFF TAGS in this file");
  1026. //return;
  1027. //}
  1028. //
  1029. // calculate the rest of the TiffToDIBData
  1030. //
  1031. int BytesPerPixel = 0;
  1032. //
  1033. // 8-bit DATA
  1034. //
  1035. if (TiffToDIBData.bmiHeader.biBitCount == 8) {
  1036. BytesPerPixel = 1;
  1037. if (TiffToDIBData.ColorsUsed == 0)
  1038. TiffToDIBData.bmiHeader.biClrUsed = 256;
  1039. else
  1040. TiffToDIBData.bmiHeader.biClrUsed = TiffToDIBData.ColorsUsed;
  1041. }
  1042. //
  1043. // 24-bit DATA
  1044. //
  1045. else if (TiffToDIBData.bmiHeader.biBitCount == 24) {
  1046. BytesPerPixel = 3;
  1047. TiffToDIBData.bmiHeader.biClrUsed = 0;
  1048. }
  1049. //
  1050. // 4-bit DATA
  1051. //
  1052. else if (TiffToDIBData.bmiHeader.biBitCount == 4) {
  1053. BytesPerPixel = 2;
  1054. TiffToDIBData.bmiHeader.biClrUsed = 256;
  1055. }
  1056. //
  1057. // 1-bit DATA
  1058. //
  1059. else {
  1060. BytesPerPixel = 0;
  1061. TiffToDIBData.bmiHeader.biClrUsed = 2;
  1062. }
  1063. TiffToDIBData.bmiHeader.biSizeImage = WIDTHBYTES((TiffToDIBData.bmiHeader.biWidth)*((DWORD)TiffToDIBData.bmiHeader.biBitCount)) * TiffToDIBData.bmiHeader.biHeight;
  1064. TiffToDIBData.bmiHeader.biPlanes = 1;
  1065. TiffToDIBData.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1066. //
  1067. // create Palette size if one exists
  1068. //
  1069. RGBQUAD* pPalette = NULL;
  1070. long PaletteSize = 0;
  1071. if (TiffToDIBData.bmiHeader.biClrUsed != 0) {
  1072. PaletteSize = TiffToDIBData.bmiHeader.biClrUsed * sizeof(RGBQUAD);
  1073. pPalette = (RGBQUAD*)GlobalAllocPtr(GHND, PaletteSize);
  1074. if (pPalette == NULL) {
  1075. AfxMessageBox("Failed to Create Palette");
  1076. return 0;
  1077. }
  1078. if (TiffToDIBData.bmiHeader.biBitCount == 8) {
  1079. if (TiffToDIBData.ColorsUsed == 0) {
  1080. //
  1081. // create a grayscale palette
  1082. //
  1083. for (int i = 0;i<(int)TiffToDIBData.bmiHeader.biClrUsed;i++) {
  1084. pPalette[i].rgbRed = (BYTE)i;
  1085. pPalette[i].rgbBlue = (BYTE)i;
  1086. pPalette[i].rgbGreen = (BYTE)i;
  1087. pPalette[i].rgbReserved = 0;
  1088. }
  1089. } else {
  1090. //
  1091. // create the color palette from colormap
  1092. //
  1093. TiffToDIBData.bmiHeader.biClrUsed = TiffToDIBData.ColorsUsed;
  1094. }
  1095. }
  1096. if (TiffToDIBData.bmiHeader.biBitCount == 1) {
  1097. //
  1098. // create a black and white palette
  1099. //
  1100. pPalette[0].rgbRed = 0;
  1101. pPalette[0].rgbBlue = 0;
  1102. pPalette[0].rgbGreen = 0;
  1103. pPalette[0].rgbReserved = 0;
  1104. pPalette[1].rgbRed = 255;
  1105. pPalette[1].rgbBlue = 255;
  1106. pPalette[1].rgbGreen = 255;
  1107. pPalette[1].rgbReserved = 255;
  1108. }
  1109. }
  1110. BITMAPFILEHEADER bmfHeader;
  1111. memset(&bmfHeader,0,sizeof(BITMAPFILEHEADER));
  1112. bmfHeader.bfType = DIB_HEADER_MARKER;
  1113. bmfHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + PaletteSize + TiffToDIBData.bmiHeader.biSizeImage;
  1114. bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ PaletteSize;
  1115. // Allocate memory for DIB info header and possible palette
  1116. m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER) + (PaletteSize*2));
  1117. if (m_pBMI == 0)
  1118. return 0;
  1119. m_pBits = (LPBYTE)GlobalAllocPtr(GHND, TiffToDIBData.bmiHeader.biSizeImage + PaletteSize);
  1120. if (m_pBits == 0) {
  1121. GlobalFreePtr(m_pBMI);
  1122. m_pBMI = NULL;
  1123. return 0;
  1124. }
  1125. BYTE* pData = m_pBits;
  1126. //
  1127. // set line width (DWORD aligned length)
  1128. //
  1129. long LineWidth = TiffToDIBData.bmiHeader.biSizeImage/TiffToDIBData.bmiHeader.biHeight;
  1130. DWORD ImageByteCount = 0;
  1131. for (i = 0;i < TiffToDIBData.OffsetCount;i++) {
  1132. //
  1133. // seek to strip
  1134. //
  1135. pPtr = pSrcDib; // move pointer to start of data
  1136. pPtr += TiffToDIBData.pStripOffsets[i]; // seek to offset
  1137. //
  1138. // read strip data (numbytes from pStripBytesCounts.
  1139. //
  1140. CopyMemory(pData,pPtr,TiffToDIBData.pStripByteCountsOffsets[i]); // read data
  1141. pData += TiffToDIBData.pStripByteCountsOffsets[i];
  1142. ImageByteCount+= TiffToDIBData.pStripByteCountsOffsets[i];
  1143. }
  1144. BYTE ColorValue = 0;
  1145. int LineCount = 1;
  1146. pData = m_pBits;
  1147. if (TiffToDIBData.bmiHeader.biClrUsed ==0) {
  1148. while (LineCount <= TiffToDIBData.bmiHeader.biHeight) {
  1149. //
  1150. // swap red and blue values
  1151. // if the data is 24-bit
  1152. //
  1153. for (int i = 0;i<LineWidth;i+=3) {
  1154. ColorValue = pData[i];
  1155. pData[i] = pData[i+2];
  1156. pData[i+2] = ColorValue;
  1157. }
  1158. pData += LineWidth;
  1159. LineCount++;
  1160. }
  1161. }
  1162. // Write BITMAPINFOHEADER to member
  1163. memmove(m_pBMI,&TiffToDIBData.bmiHeader,sizeof(BITMAPINFOHEADER));
  1164. if (TiffToDIBData.bmiHeader.biClrUsed >0) {
  1165. memmove(m_pBMI->bmiColors,pPalette,PaletteSize);
  1166. }
  1167. if (TiffToDIBData.bmiHeader.biBitCount == 1)
  1168. LineWidth = (long)ceil((float)TiffToDIBData.bmiHeader.biWidth/8.0f);
  1169. else
  1170. LineWidth = TiffToDIBData.bmiHeader.biWidth * BytesPerPixel;
  1171. pData = m_pBits;
  1172. //
  1173. // check DWORD alignment of data
  1174. //
  1175. if ((LineWidth % sizeof(DWORD))) {
  1176. //
  1177. // Pad data
  1178. //
  1179. int PaddedBytes = sizeof(DWORD) - (LineWidth % sizeof(DWORD));
  1180. LineCount = 1;
  1181. BYTE* pCurrent = NULL;
  1182. BYTE* pDest = NULL;
  1183. for (LineCount = TiffToDIBData.bmiHeader.biHeight;LineCount > 1;LineCount--) {
  1184. pCurrent = pData + (LineWidth*(LineCount - 1));
  1185. pDest = pCurrent + (PaddedBytes*(LineCount - 1));
  1186. memmove(pDest,pCurrent,(LineWidth + PaddedBytes));
  1187. }
  1188. }
  1189. if (pPalette)
  1190. GlobalFreePtr(pPalette);
  1191. if (TiffToDIBData.pStripByteCountsOffsets != NULL)
  1192. GlobalFree(TiffToDIBData.pStripByteCountsOffsets);
  1193. if (TiffToDIBData.pStripOffsets != NULL)
  1194. GlobalFree(TiffToDIBData.pStripOffsets);
  1195. //
  1196. // flip the data because we are converting it
  1197. // to DIB form
  1198. //
  1199. Flip(m_pBits);
  1200. CreatePalette();
  1201. } else {
  1202. BOOL bTopDown = FALSE;
  1203. LPBYTE pSrcDib = (LPBYTE)GlobalLock(hGlobal);
  1204. LPBITMAPINFO pbmi = NULL;
  1205. pbmi = (LPBITMAPINFO)pSrcDib;
  1206. // Allocate memory for DIB
  1207. m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, (sizeof(BITMAPINFO) + pbmi->bmiHeader.biClrUsed * sizeof(RGBQUAD)));
  1208. if (m_pBMI == 0)
  1209. return 0;
  1210. // copy header.
  1211. memmove(m_pBMI,pbmi,(sizeof(BITMAPINFO) + pbmi->bmiHeader.biClrUsed * sizeof(RGBQUAD)));
  1212. DWORD dwLength = m_pBMI->bmiHeader.biSizeImage;
  1213. // if a TOP_DOWN_DIB comes in..adjust it to be displayed
  1214. // this is not a normal thing to do here. It is only so that the
  1215. // image can be displayed for debug reasons.
  1216. if (m_pBMI->bmiHeader.biHeight < 1) {
  1217. bTopDown = TRUE;
  1218. m_pBMI->bmiHeader.biHeight = -m_pBMI->bmiHeader.biHeight;
  1219. }
  1220. // Alloc memory for bits
  1221. m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwLength);
  1222. if (m_pBits == 0) {
  1223. GlobalFreePtr(m_pBMI);
  1224. m_pBMI = NULL;
  1225. return 0;
  1226. }
  1227. // move pointer past BITMAPINFOHEADER to bits
  1228. pSrcDib+=sizeof(BITMAPINFOHEADER);
  1229. pSrcDib+=(m_pBMI->bmiHeader.biClrUsed * sizeof(RGBQUAD));
  1230. if (bTopDown) {
  1231. // flip bitmap and copy bits
  1232. Flip(pSrcDib);
  1233. memmove(m_pBits,pSrcDib,dwLength);
  1234. } else
  1235. // copy bits
  1236. memmove(m_pBits,pSrcDib,dwLength);
  1237. CreatePalette();
  1238. GlobalUnlock(hGlobal);
  1239. }
  1240. return TRUE;
  1241. }
  1242. /**************************************************************************\
  1243. * CDib::GotImage()
  1244. *
  1245. * Check DIB to see is memory has been allocated and used.
  1246. *
  1247. *
  1248. * Arguments:
  1249. *
  1250. * none
  1251. *
  1252. * Return Value:
  1253. *
  1254. * status
  1255. *
  1256. * History:
  1257. *
  1258. * 2/14/1999 Original Version
  1259. *
  1260. \**************************************************************************/
  1261. BOOL CDib::GotImage()
  1262. {
  1263. // Make sure all member data that might have been allocated exist.
  1264. if (m_pBits)
  1265. if (m_pBMI)
  1266. return TRUE;
  1267. return FALSE;
  1268. }
  1269. /**************************************************************************\
  1270. * CDib::ReadFromBMPFile()
  1271. *
  1272. * Opens and Reads data from a BMP file into DIB form
  1273. *
  1274. *
  1275. * Arguments:
  1276. *
  1277. * LPSTR- filename (Filename to be opened and read)
  1278. *
  1279. * Return Value:
  1280. *
  1281. * void
  1282. *
  1283. * History:
  1284. *
  1285. * 2/14/1999 Original Version
  1286. *
  1287. \**************************************************************************/
  1288. void CDib::ReadFromBMPFile(LPSTR filename)
  1289. {
  1290. CFile ImageFile;
  1291. // open & read image file
  1292. ImageFile.Open(filename,CFile::modeRead,NULL);
  1293. Read(ImageFile,BMP_IMAGE);
  1294. // close image file
  1295. ImageFile.Close();
  1296. }
  1297. /**************************************************************************\
  1298. * CDib::ReadFromBMPFile()
  1299. *
  1300. * Opens and Reads data from a BMP file into DIB form
  1301. *
  1302. *
  1303. * Arguments:
  1304. *
  1305. * CString- filename (Filename to be opened and read)
  1306. *
  1307. * Return Value:
  1308. *
  1309. * void
  1310. *
  1311. * History:
  1312. *
  1313. * 2/14/1999 Original Version
  1314. *
  1315. \**************************************************************************/
  1316. void CDib::ReadFromBMPFile(CString filename)
  1317. {
  1318. CFile ImageFile;
  1319. // open & read image file
  1320. ImageFile.Open(filename,CFile::modeRead,NULL);
  1321. Read(ImageFile,BMP_IMAGE);
  1322. // close image file
  1323. ImageFile.Close();
  1324. }
  1325. /**************************************************************************\
  1326. * CDib::ReadFromTIFFFile()
  1327. *
  1328. * Opens and Reads data from a TIFF file into DIB form
  1329. *
  1330. *
  1331. * Arguments:
  1332. *
  1333. * CString- filename (Filename to be opened and read)
  1334. *
  1335. * Return Value:
  1336. *
  1337. * void
  1338. *
  1339. * History:
  1340. *
  1341. * 4/14/1999 Original Version
  1342. *
  1343. \**************************************************************************/
  1344. void CDib::ReadFromTIFFFile(CString filename)
  1345. {
  1346. CFile ImageFile;
  1347. // open & read image file
  1348. ImageFile.Open(filename,CFile::modeRead,NULL);
  1349. Read(ImageFile,TIFF_IMAGE);
  1350. // close image file
  1351. ImageFile.Close();
  1352. }
  1353. /**************************************************************************\
  1354. * CDib::Flip()
  1355. *
  1356. * Flips a DIB, TOPDOWN to DIB conversion
  1357. *
  1358. *
  1359. * Arguments:
  1360. *
  1361. * pSrcData - TOPDOWN DIB to be flipped
  1362. *
  1363. * Return Value:
  1364. *
  1365. * status
  1366. *
  1367. * History:
  1368. *
  1369. * 2/14/1999 Original Version
  1370. *
  1371. \**************************************************************************/
  1372. BOOL CDib::Flip(BYTE* pSrcData)
  1373. {
  1374. LONG Width = 0;
  1375. LONG Height = 0;
  1376. LONG Linelength = 0;
  1377. LONG BitCount = 0;
  1378. Width = m_pBMI->bmiHeader.biWidth;
  1379. Height = m_pBMI->bmiHeader.biHeight;
  1380. BitCount = m_pBMI->bmiHeader.biBitCount;
  1381. Linelength = (((Width*BitCount+31)/32)*4);
  1382. LONG nLineWidthInBytes = Linelength;
  1383. PBYTE pLine = new BYTE[nLineWidthInBytes];
  1384. for (int i=0;i<Height/2;i++) {
  1385. PBYTE pSrc = pSrcData + (i * nLineWidthInBytes);
  1386. PBYTE pDst = pSrcData + ((Height-i-1) * nLineWidthInBytes);
  1387. CopyMemory( pLine, pSrc, nLineWidthInBytes );
  1388. CopyMemory( pSrc, pDst, nLineWidthInBytes );
  1389. CopyMemory( pDst, pLine, nLineWidthInBytes );
  1390. }
  1391. delete[] pLine;
  1392. return TRUE;
  1393. }
  1394. /**************************************************************************\
  1395. * CDib::Dump(), CopyToHandle(), ReadFromHandle(), and Serialize()
  1396. *
  1397. * Misc. member functions that are not used at this time
  1398. *
  1399. *
  1400. * Arguments:
  1401. *
  1402. * -
  1403. *
  1404. * Return Value:
  1405. *
  1406. * -
  1407. *
  1408. * History:
  1409. *
  1410. * 2/14/1999 Original Version
  1411. *
  1412. \**************************************************************************/
  1413. #ifdef _DEBUG
  1414. // Dump
  1415. void CDib::Dump(CDumpContext& dc) const
  1416. {
  1417. CObject::Dump(dc);
  1418. }
  1419. #endif
  1420. // CopyToHandle
  1421. HGLOBAL CDib::CopyToHandle() const
  1422. {
  1423. CSharedFile file;
  1424. try {
  1425. if (Save(file)==0)
  1426. return 0;
  1427. } catch (CFileException* e) {
  1428. e->Delete();
  1429. return 0;
  1430. }
  1431. return file.Detach();
  1432. }
  1433. // ReadFromHandle
  1434. DWORD CDib::ReadFromHandle(HGLOBAL hGlobal)
  1435. {
  1436. CSharedFile file;
  1437. file.SetHandle(hGlobal, FALSE);
  1438. DWORD dwResult = Read(file,BMP_IMAGE);
  1439. file.Detach();
  1440. return dwResult;
  1441. }
  1442. // Serialize
  1443. void CDib::Serialize(CArchive& ar)
  1444. {
  1445. CFile* pFile = ar.GetFile();
  1446. ASSERT(pFile != NULL);
  1447. if (ar.IsStoring()) { // storing code
  1448. Save(*pFile);
  1449. } else { // loading code
  1450. Read(*pFile,BMP_IMAGE);
  1451. }
  1452. }