home *** CD-ROM | disk | FTP | other *** search
- //***********************************************************************
- //
- // MTDoc.cpp
- //
- //***********************************************************************
-
- #include <afxwin.h>
- #include <afxmt.h>
- #include "Resource.h"
- #include "MTDoc.h"
-
- UINT ThreadFunc (LPVOID);
- LOGPALETTE* CreateGrayScale ();
-
- IMPLEMENT_DYNCREATE (CMTDoc, CDocument)
-
- BEGIN_MESSAGE_MAP (CMTDoc, CDocument)
- ON_COMMAND (ID_EFFECTS_GRAY_SCALE, OnGrayScale)
- ON_UPDATE_COMMAND_UI (ID_EFFECTS_GRAY_SCALE, OnUpdateGrayScaleUI)
- END_MESSAGE_MAP ()
-
- CMTDoc::CMTDoc ()
- {
- m_hThread = NULL;
- m_bWorking = FALSE;
- }
-
- void CMTDoc::OnGrayScale ()
- {
- if (!m_bWorking) {
- m_threadParms.pWnd = AfxGetMainWnd ();
- m_threadParms.pBitmap = &m_bitmap;
- m_threadParms.pPalette = &m_palette;
- m_threadParms.pCriticalSection = &m_criticalSection;
- m_threadParms.pEvent = &m_event;
-
- m_bWorking = TRUE;
- m_event.ResetEvent (); // Just to be sure
- CWinThread* pThread = AfxBeginThread (ThreadFunc, &m_threadParms);
- m_hThread = pThread->m_hThread;
- }
- else // Kill the thread
- m_event.SetEvent ();
- }
-
- void CMTDoc::ThreadFinished ()
- {
- ::WaitForSingleObject (m_hThread, INFINITE);
- m_bWorking = FALSE;
-
- if ((HPALETTE) m_palette != NULL) {
- m_palette.DeleteObject ();
- LOGPALETTE* pLP = CreateGrayScale ();
- m_palette.CreatePalette (pLP);
- delete[] pLP;
- }
- UpdateAllViews (NULL, 0, NULL);
- }
-
- void CMTDoc::ThreadAborted ()
- {
- ::WaitForSingleObject (m_hThread, INFINITE);
- m_bWorking = FALSE;
- }
-
- void CMTDoc::OnUpdateGrayScaleUI (CCmdUI* pCmdUI)
- {
- if (m_bWorking) {
- pCmdUI->SetText ("Stop &Gray Scale Conversion");
- pCmdUI->Enable ();
- }
- else {
- pCmdUI->SetText ("Convert to &Gray Scale");
- pCmdUI->Enable ((HBITMAP) m_bitmap != NULL);
- }
- }
-
- BOOL CMTDoc::OnOpenDocument (LPCTSTR lpszPathName)
- {
- if (m_bWorking) {
- AfxMessageBox ("You must stop the gray scale conversion " \
- "before opening another document", MB_ICONSTOP | MB_OK);
- return FALSE;
- }
-
- if (!CDocument::OnOpenDocument (lpszPathName)) {
- POSITION pos = GetFirstViewPosition ();
- CView* pView = GetNextView (pos);
- pView->OnInitialUpdate ();
- return FALSE;
- }
-
- // Return now if this device doesn't support palettes
- CClientDC dc (AfxGetMainWnd ());
- if ((dc.GetDeviceCaps (RASTERCAPS) & RC_PALETTE) == 0)
- return TRUE;
-
- // Create a palette to go with the DIB section
- if ((HBITMAP) m_bitmap != NULL) {
- DIBSECTION ds;
- m_bitmap.GetObject (sizeof (DIBSECTION), &ds);
-
- int nColors;
- if (ds.dsBmih.biClrUsed != 0)
- nColors = ds.dsBmih.biClrUsed;
- else
- nColors = 1 << ds.dsBmih.biBitCount;
-
- // Create a halftone palette if the DIB section contains more
- // than 256 colors
- if (nColors > 256)
- m_palette.CreateHalftonePalette (&dc);
-
- // Create a custom palette from the DIB section's color table
- // if the number of colors is 256 or less
- else {
- RGBQUAD* pRGB = new RGBQUAD[nColors];
-
- CDC memDC;
- memDC.CreateCompatibleDC (&dc);
- m_criticalSection.Lock ();
- CBitmap* pOldBitmap = memDC.SelectObject (&m_bitmap);
- ::GetDIBColorTable ((HDC) memDC, 0, nColors, pRGB);
- memDC.SelectObject (pOldBitmap);
- m_criticalSection.Unlock ();
-
- UINT nSize = sizeof (LOGPALETTE) +
- (sizeof (PALETTEENTRY) * (nColors - 1));
- LOGPALETTE* pLP = (LOGPALETTE*) new BYTE[nSize];
-
- pLP->palVersion = 0x300;
- pLP->palNumEntries = nColors;
-
- for (int i=0; i<nColors; i++) {
- pLP->palPalEntry[i].peRed = pRGB[i].rgbRed;
- pLP->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
- pLP->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
- pLP->palPalEntry[i].peFlags = 0;
- }
-
- m_palette.CreatePalette (pLP);
- delete[] pLP;
- delete[] pRGB;
- }
- }
- return TRUE;
- }
-
- void CMTDoc::DeleteContents ()
- {
- if ((HBITMAP) m_bitmap != NULL)
- m_bitmap.DeleteObject ();
-
- if ((HPALETTE) m_palette != NULL)
- m_palette.DeleteObject ();
-
- CDocument::DeleteContents();
- }
-
- void CMTDoc::Serialize (CArchive& ar)
- {
- if (ar.IsLoading ()) {
- CString strFileName = ar.GetFile ()->GetFilePath ();
-
- HBITMAP hBitmap = (HBITMAP) ::LoadImage (AfxGetInstanceHandle (),
- (LPCTSTR) strFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE |
- LR_CREATEDIBSECTION);
-
- if (hBitmap == NULL)
- AfxThrowArchiveException (CArchiveException::badIndex);
-
- m_bitmap.Attach (hBitmap);
- }
- }
-
- CBitmap* CMTDoc::GetBitmap ()
- {
- return ((HBITMAP) m_bitmap == NULL) ? NULL : &m_bitmap;
- }
-
- CPalette* CMTDoc::GetPalette ()
- {
- return ((HPALETTE) m_palette == NULL) ? NULL : &m_palette;
- }
-
- /////////////////////////////////////////////////////////////////////////
- // Thread function and other globals
-
- UINT ThreadFunc (LPVOID pParam)
- {
- THREADPARMS* pThreadParms = (THREADPARMS*) pParam;
- CWnd* pWnd = pThreadParms->pWnd;
- CBitmap* pBitmap = pThreadParms->pBitmap;
- CPalette* pPalette = pThreadParms->pPalette;
- CCriticalSection* pCriticalSection = pThreadParms->pCriticalSection;
- CEvent* pKillThread = pThreadParms->pEvent;
-
- DIBSECTION ds;
- pBitmap->GetObject (sizeof (DIBSECTION), &ds);
- int nWidth = ds.dsBm.bmWidth;
- int nHeight = ds.dsBm.bmHeight;
-
- // Initialize one memory DC (memDC2) to hold a color copy of the
- // image and another memory DC (memDC1) to hold a gray scale copy
- CClientDC dc (pWnd);
- CBitmap bitmap1, bitmap2;
- bitmap1.CreateCompatibleBitmap (&dc, nWidth, nHeight);
- bitmap2.CreateCompatibleBitmap (&dc, nWidth, nHeight);
-
- CDC memDC1, memDC2;
- memDC1.CreateCompatibleDC (&dc);
- memDC2.CreateCompatibleDC (&dc);
- CBitmap* pOldBitmap1 = memDC1.SelectObject (&bitmap1);
- CBitmap* pOldBitmap2 = memDC2.SelectObject (&bitmap2);
-
- CPalette* pOldPalette1 = NULL;
- CPalette* pOldPalette2 = NULL;
- CPalette grayPalette;
-
- if (pPalette->m_hObject != NULL) {
- LOGPALETTE* pLP = CreateGrayScale ();
- grayPalette.CreatePalette (pLP);
- delete[] pLP;
-
- pOldPalette1 = memDC1.SelectPalette (&grayPalette, FALSE);
- pOldPalette2 = memDC2.SelectPalette (pPalette, FALSE);
- memDC1.RealizePalette ();
- memDC2.RealizePalette ();
- }
-
- // Copy the bitmap to memDC2
- CDC memDC3;
- memDC3.CreateCompatibleDC (&dc);
- pCriticalSection->Lock ();
- CBitmap* pOldBitmap3 = memDC3.SelectObject (pBitmap);
- memDC2.BitBlt (0, 0, nWidth, nHeight, &memDC3, 0, 0, SRCCOPY);
- memDC3.SelectObject (pOldBitmap3);
- pCriticalSection->Unlock ();
-
- // Convert the colors in memDC2 to shades of gray in memDC1
- int x, y;
- COLORREF crColor;
- BYTE grayLevel;
-
- for (y=0; y<nHeight; y++) {
- for (x=0; x<nWidth; x++) {
- crColor = memDC2.GetPixel (x, y);
- grayLevel = (BYTE)
- (((((UINT) GetRValue (crColor)) * 30) +
- (((UINT) GetGValue (crColor)) * 59) +
- (((UINT) GetBValue (crColor)) * 11)) / 100);
- memDC1.SetPixel (x, y,
- PALETTERGB (grayLevel, grayLevel, grayLevel));
- }
-
- // Kill the thread if the pKillThread event is signaled
- if (::WaitForSingleObject (pKillThread->m_hObject, 0) ==
- WAIT_OBJECT_0) {
-
- memDC1.SelectObject (pOldBitmap1);
- memDC2.SelectObject (pOldBitmap2);
-
- if (pPalette->m_hObject != NULL) {
- memDC1.SelectPalette (pOldPalette1, FALSE);
- memDC2.SelectPalette (pOldPalette2, FALSE);
- }
- pWnd->PostMessage (WM_USER_THREAD_ABORTED, y + 1, 0);
- return (UINT) -1;
- }
- pWnd->PostMessage (WM_USER_THREAD_UPDATE, y + 1, nHeight);
- }
-
- // Copy the gray scale image over the original bitmap
- CPalette* pOldPalette3 = NULL;
- if (pPalette->m_hObject != NULL) {
- pOldPalette3 = memDC3.SelectPalette (&grayPalette, FALSE);
- memDC3.RealizePalette ();
- }
- pCriticalSection->Lock ();
- pOldBitmap3 = memDC3.SelectObject (pBitmap);
- memDC3.BitBlt (0, 0, nWidth, nHeight, &memDC1, 0, 0, SRCCOPY);
- memDC3.SelectObject (pOldBitmap3);
- pCriticalSection->Unlock ();
-
- // Clean up the memory DCs
- memDC1.SelectObject (pOldBitmap1);
- memDC2.SelectObject (pOldBitmap2);
-
- if (pPalette->m_hObject != NULL) {
- memDC1.SelectPalette (pOldPalette1, FALSE);
- memDC2.SelectPalette (pOldPalette2, FALSE);
- memDC3.SelectPalette (pOldPalette3, FALSE);
- }
-
- // Tell the frame window we're done
- pWnd->PostMessage (WM_USER_THREAD_FINISHED, 0, 0);
- return 0;
- }
-
- LOGPALETTE* CreateGrayScale ()
- {
- UINT nSize = sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 63);
- LOGPALETTE* pLP = (LOGPALETTE*) new BYTE[nSize];
-
- pLP->palVersion = 0x300;
- pLP->palNumEntries = 64;
-
- for (int i=0; i<64; i++) {
- pLP->palPalEntry[i].peRed = i * 4;
- pLP->palPalEntry[i].peGreen = i * 4;
- pLP->palPalEntry[i].peBlue = i * 4;
- pLP->palPalEntry[i].peFlags = 0;
- }
- return pLP;
- }
-