/*! Create a DIB from current bitmap // \param HDC hdcSRC : */ BOOL CAxJpgCard::CreateDib(HDC hdcSRC) { BITMAP bm; UINT iColorDataType; // color data type (palette or RGB values) ::GetObject( m_hCurrentBitmap, sizeof(bm), (LPVOID)&bm ); HDC hdcComp = CreateCompatibleDC(hdcSRC); iColorDataType = DIB_RGB_COLORS; // create a DIB DIBINFO DIBinfo; BITMAPINFOHEADER& bih = DIBinfo.bmiHeader; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = bm.bmWidth ; bih.biHeight = bm.bmHeight; bih.biPlanes = 1; // Must always be 1 according to docs bih.biBitCount = bm.bmBitsPixel; bih.biCompression = BI_RGB; bih.biSizeImage = BytesPerLine(bm.bmHeight, bm.bmBitsPixel) * bm.bmWidth; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0; if (!::GetDIBits(hdcComp, m_hCurrentBitmap, 0, bm.bmHeight, NULL, DIBinfo, iColorDataType)) { ATLTRACE("Unable to GetDIBits\n"); } BYTE* pvBitsSRC = (BYTE*)bm.bmBits; BYTE* pvBitsDST = NULL; // create dib for rotated image with bitmap set to all null HBITMAP hCurrentDib = ::CreateDIBSection(hdcComp , (const BITMAPINFO*) DIBinfo, DIB_RGB_COLORS, (VOID**)&pvBitsDST, NULL, 0); ATLASSERT( hCurrentDib != NULL); DWORD dwImageSize = DIBinfo.bmiHeader.biSizeImage; if (dwImageSize == 0) { int nBytesPerLine = BytesPerLine(DIBinfo.bmiHeader.biWidth, DIBinfo.bmiHeader.biBitCount); dwImageSize = nBytesPerLine * DIBinfo.bmiHeader.biHeight; } CreateHalftonePalette(DIBinfo, 256); m_hCurrentBitmap = hCurrentDib; //memcpy(pvBitsDST, pvBitsSRC, dwImageSize); return TRUE; }
BOOL CDIB::SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits) { // DeleteObject(); if (!lpBitmapInfo || !lpBits) return FALSE; HDC hDC = NULL; BITMAPINFOHEADER& bmih = lpBitmapInfo->bmiHeader; // Compute the number of colors in the color table m_iColorTableSize = NumColorEntries(bmih.biBitCount, bmih.biCompression); DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD); // Copy over BITMAPINFO contents memcpy(&m_DIBinfo, lpBitmapInfo, dwBitmapInfoSize); // Should now have all the info we need to create the sucker. //TRACE(_T("Width %d, Height %d, Bits/pixel %d, Image Size %d\n"), // bmih.biWidth, bmih.biHeight, bmih.biBitCount, bmih.biSizeImage); // Create a DC which will be used to get DIB, then create DIBsection hDC = ::GetDC(NULL); if (!hDC) { TRACE0("Unable to get DC\n"); return FALSE; } m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo, m_iColorDataType, &m_ppvBits, NULL, 0); ::ReleaseDC(NULL, hDC); if (!m_hBitmap) { TRACE0("CreateDIBSection failed\n"); return FALSE; } if (m_DIBinfo.bmiHeader.biSizeImage == 0) { int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth, lpBitmapInfo->bmiHeader.biBitCount); m_DIBinfo.bmiHeader.biSizeImage = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight; } memcpy(m_ppvBits, lpBits, m_DIBinfo.bmiHeader.biSizeImage); #ifndef DIBSECTION_NO_PALETTE if (!CreatePalette()) { TRACE0("Unable to create palette\n"); return FALSE; } #endif // DIBSECTION_NO_PALETTE return TRUE; }
/**************************************************************************** * * FUNCTION: DIBToIconImage * * PURPOSE: Converts a CF_DIB memory block to an icon image * * PARAMS: LPICONIMAGE lpii - pointer to icon image data * LPBYTE lpDIB - a pointer to the CF_DIB block * BOOL bStretchToFit - TRUE to stretch, FALSE to take * the upper left corner of the DIB * * RETURNS: BOOL - TRUE for success, FALSE for failure * * History: * July '95 - Created * \****************************************************************************/ BOOL DIBToIconImage( LPICONIMAGE lpii, LPBYTE lpDIB, BOOL bStretch ) { LPBYTE lpNewDIB; // Sanity check if( lpDIB == NULL ) return FALSE; // Let the DIB engine convert color depths if need be lpNewDIB = ConvertDIBFormat( (LPBITMAPINFO)lpDIB, lpii->Width, lpii->Height, lpii->Colors, bStretch ); // Now we have a cool new DIB of the proper size/color depth // Lets poke it into our data structures and be done with it // How big is it? lpii->dwNumBytes = sizeof( BITMAPINFOHEADER ) // Header + PaletteSize( (LPSTR)lpNewDIB ) // Palette + lpii->Height * BytesPerLine( (LPBITMAPINFOHEADER)lpNewDIB ) // XOR mask + lpii->Height * WIDTHBYTES( lpii->Width ); // AND mask // If there was already an image here, free it if( lpii->lpBits != NULL ) free( lpii->lpBits ); // Allocate enough room for the new image if( (lpii->lpBits = malloc( lpii->dwNumBytes )) == NULL ) { free( lpii ); return FALSE; } // Copy the bits memcpy( lpii->lpBits, lpNewDIB, sizeof( BITMAPINFOHEADER ) + PaletteSize( (LPSTR)lpNewDIB ) ); // Adjust internal pointers/variables for new image lpii->lpbi = (LPBITMAPINFO)(lpii->lpBits); lpii->lpbi->bmiHeader.biHeight *= 2; lpii->lpXOR = FindDIBBits( (LPSTR)(lpii->lpBits) ); memcpy( lpii->lpXOR, FindDIBBits((LPSTR)lpNewDIB), lpii->Height * BytesPerLine( (LPBITMAPINFOHEADER)lpNewDIB ) ); lpii->lpAND = lpii->lpXOR + lpii->Height * BytesPerLine( (LPBITMAPINFOHEADER)lpNewDIB ); memset( lpii->lpAND, 0, lpii->Height * WIDTHBYTES( lpii->Width ) ); // Free the source free( lpNewDIB ); return TRUE; }
/**************************************************************************** * * FUNCTION: WriteBMPFile * * PURPOSE: Writes a BMP file from CF_DIB format * * PARAMS: LPCTSTR szFileName - the name of the file to read * LPBYTE - pointer to the CF_DIB, NULL for failure * * RETURNS: BOOL - TRUE for success, FALSE for Failure * * History: * July '95 - Created * \****************************************************************************/ BOOL WriteBMPFile( LPCTSTR szFileName, LPBYTE lpDIB ) { HANDLE hFile; BITMAPFILEHEADER bfh; DWORD dwBytes, dwBytesToWrite; LPBITMAPINFOHEADER lpbmih; // Open the file if( (hFile=CreateFile( szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE ) { MessageBox( NULL, "Error opening file", szFileName, MB_OK ); return FALSE; } bfh.bfType = 0x4d42; bfh.bfReserved1 = 0; bfh.bfReserved2 = 0; bfh.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + PaletteSize( lpDIB ); bfh.bfSize = (bfh.bfOffBits + ((LPBITMAPINFOHEADER)lpDIB)->biHeight * BytesPerLine((LPBITMAPINFOHEADER)lpDIB))/4; // Write the header if( ( ! WriteFile( hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwBytes, NULL ) ) || ( dwBytes != sizeof( BITMAPFILEHEADER ) ) ) { CloseHandle( hFile ); MessageBox( NULL, "Error Writing file", szFileName, MB_OK ); return FALSE; } lpbmih = (LPBITMAPINFOHEADER)lpDIB; lpbmih->biHeight /= 2; dwBytesToWrite = bfh.bfOffBits + (lpbmih->biHeight * BytesPerLine(lpbmih)); if( ( ! WriteFile( hFile, lpDIB, dwBytesToWrite, &dwBytes, NULL ) ) || ( dwBytes != dwBytesToWrite ) ) { CloseHandle( hFile ); MessageBox( NULL, "Error Writing file", szFileName, MB_OK ); return FALSE; } lpbmih->biHeight *= 2; CloseHandle( hFile ); return TRUE; }
Bitmap::Bitmap(const Graphics& g, const Bitmap& bitmap) { if (this == &bitmap) return; m_platformBitmap = ThePlatformFactory->CreatePlatformBitmap( g.GetPlatformGraphics(), bitmap.Width(), bitmap.Height(), bitmap.BitsPerPixel()); uchar* bits = new uchar[Height() * BytesPerLine()]; bitmap.GetBits(g, bits, 0, Height(), BitsPerPixel()); SetBits(g, bits, 0, Height(), BitsPerPixel()); delete[] bits; }
/************************************************************************* * * ReverseDIB() * * Parameters: * * HDIB hDib - objective DIB handle * * Return Value: * * BOOL - True is success, else False * * Description: * * This function reverse DIB * ************************************************************************/ BOOL ReverseDIB(HDIB hDib) { WaitCursorBegin(); HDIB hNewDib = NULL; // only support 256 grayscale image WORD wBitCount = DIBBitCount(hDib); if (wBitCount != 8) { WaitCursorEnd(); return FALSE; } // the maxium pixel value int nMaxValue = 256; // source pixel data LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib); if (! lpSrcDIB) { WaitCursorBegin(); return FALSE; } // new DIB attributes LPSTR lpPtr; LONG lHeight = DIBHeight(lpSrcDIB); LONG lWidth = DIBWidth(lpSrcDIB); DWORD dwBufferSize = GlobalSize(lpSrcDIB); int nLineBytes = BytesPerLine(lpSrcDIB); // convolute... for (long i=0; i<lHeight; i++) for (long j=0; j<lWidth; j++) { lpPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-i*nLineBytes)+j; *lpPtr = nMaxValue - *lpPtr; } // cleanup GlobalUnlock(hDib); WaitCursorEnd(); return TRUE; }
BOOL CDib::SetBitmap(const LPBITMAPINFO lpBitmapInfo, const LPVOID lpBits) { DeleteObject(); if (!lpBitmapInfo || !lpBits) return FALSE; HDC hDC = NULL; DWORD dwBitmapInfoSize = sizeof(BITMAPINFO); memcpy(&m_BMinfo, lpBitmapInfo, dwBitmapInfoSize); hDC = ::GetDC(NULL); if (!hDC) { DeleteObject(); return FALSE; } m_hBitmap = CreateDIBSection(hDC, &m_BMinfo, DIB_RGB_COLORS, &m_pBits, NULL, 0); ::ReleaseDC(NULL, hDC); if (!m_hBitmap) { DeleteObject(); return FALSE; } DWORD dwImageSize = m_BMinfo.bmiHeader.biSizeImage; if (dwImageSize == 0) { int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth, lpBitmapInfo->bmiHeader.biBitCount); dwImageSize = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight; } GdiFlush(); memcpy(m_pBits, lpBits, dwImageSize); return TRUE; }
/**************************************************************************** * * FUNCTION: AdjustIconImagePointers * * PURPOSE: Adjusts internal pointers in icon resource struct * * PARAMS: LPICONIMAGE lpImage - the resource to handle * * RETURNS: BOOL - TRUE for success, FALSE for failure * * History: * July '95 - Created * \****************************************************************************/ BOOL AdjustIconImagePointers( LPICONIMAGE lpImage ) { // Sanity check if( lpImage==NULL ) return FALSE; // BITMAPINFO is at beginning of bits lpImage->lpbi = (LPBITMAPINFO)lpImage->lpBits; // Width - simple enough lpImage->Width = lpImage->lpbi->bmiHeader.biWidth; // Icons are stored in funky format where height is doubled - account for it lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2; // How many colors? lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * lpImage->lpbi->bmiHeader.biBitCount; // XOR bits follow the header and color table lpImage->lpXOR = FindDIBBits((LPSTR)lpImage->lpbi); // AND bits follow the XOR bits lpImage->lpAND = lpImage->lpXOR + (lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER)(lpImage->lpbi))); return TRUE; }
BOOL CIconExtractor::AdjustIconImagePointers(LPICONIMAGE lpImage) { if (!lpImage) return FALSE; // BITMAPINFO is at beginning of bits lpImage->lpbi = reinterpret_cast<LPBITMAPINFO>(lpImage->lpBits); // Width - simple enough lpImage->Width = lpImage->lpbi->bmiHeader.biWidth; // Icons are stored in funky format where height is doubled - account for it lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight) / 2; // How many colors? lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * lpImage->lpbi->bmiHeader.biBitCount; // XOR bits follow the header and color table lpImage->lpXOR = reinterpret_cast<PBYTE>(FindDIBBits(reinterpret_cast<LPSTR>(lpImage->lpbi))); // AND bits follow the XOR bits lpImage->lpAND = lpImage->lpXOR + (lpImage->Height * BytesPerLine(reinterpret_cast<LPBITMAPINFOHEADER>(lpImage->lpbi))); return TRUE; }
std::shared_ptr<Image> Visualizer::CaptureDepthFloatBuffer( bool do_render/* = true*/) { Image depth_image; depth_image.PrepareImage(view_control_ptr_->GetWindowWidth(), view_control_ptr_->GetWindowHeight(), 1, 4); if (do_render) { Render(); is_redraw_required_ = false; } glFinish(); #if __APPLE__ // On OSX with Retina display and glfw3, there is a bug with glReadPixels(). // When using glReadPixels() to read a block of depth data. The data is // horizontally stretched (vertically it is fine). This issue is related // to GLFW_SAMPLES hint. When it is set to 0 (anti-aliasing disabled), // glReadPixels() works fine. See this post for details: // http://stackoverflow.com/questions/30608121/glreadpixel-one-pass-vs-looping-through-points // The reason of this bug is unknown. The current workaround is to read // depth buffer column by column. This is 15~30 times slower than one block // reading glReadPixels(). std::vector<float> float_buffer(depth_image.height_); float *p = (float *)depth_image.data_.data(); for (int j = 0; j < depth_image.width_; j++) { glReadPixels(j, 0, 1, depth_image.width_, GL_DEPTH_COMPONENT, GL_FLOAT, float_buffer.data()); for (int i = 0; i < depth_image.height_; i++) { p[i * depth_image.width_ + j] = float_buffer[i]; } } #else //__APPLE__ // By default, glReadPixels read a block of depth buffer. glReadPixels(0, 0, depth_image.width_, depth_image.height_, GL_DEPTH_COMPONENT, GL_FLOAT, depth_image.data_.data()); #endif //__APPLE__ // glReadPixels get the screen in a vertically flipped manner // We should flip it back, and convert it to the correct depth value auto image_ptr = std::make_shared<Image>(); double z_near = view_control_ptr_->GetZNear(); double z_far = view_control_ptr_->GetZFar(); image_ptr->PrepareImage(view_control_ptr_->GetWindowWidth(), view_control_ptr_->GetWindowHeight(), 1, 4); for (int i = 0; i < depth_image.height_; i++) { float *p_depth = (float *)(depth_image.data_.data() + depth_image.BytesPerLine() * (depth_image.height_ - i - 1)); float *p_image = (float *)(image_ptr->data_.data() + image_ptr->BytesPerLine() * i); for (int j = 0; j < depth_image.width_; j++) { if (p_depth[j] == 1.0) { continue; } double z_depth = 2.0 * z_near * z_far / (z_far + z_near - (2.0 * (double)p_depth[j] - 1.0) * (z_far - z_near)); p_image[j] = (float)z_depth; } } return image_ptr; }
/**************************************************************************** * * FUNCTION: MakeNewANDMaskBasedOnPoint * * PURPOSE: Creates a new AND mask for the icon image * * PARAMS: LPICONIMAGE lpIcon - pointer to icon image data * POINT pt - coords of transparent pixel * * RETURNS: BOOL - TRUE for success, FALSE for failure * * COMMENTS: Creates the AND mask using the color of the pixel at pt * as a transparent color. The XOR mask is changed as well. * This is because the OS expects the XOR mask to have the * AND mask already applied (ie black in transparent areas) * * History: * July '95 - Created * \****************************************************************************/ BOOL MakeNewANDMaskBasedOnPoint( LPICONIMAGE lpIcon, POINT pt ) { HBITMAP hXORBitmap, hOldXORBitmap; HDC hDC, hMemDC1; LPBYTE pXORBits; COLORREF crTransparentColor; LONG i,j; // Account for height*2 thing lpIcon->lpbi->bmiHeader.biHeight /= 2; // Need a DC hDC = GetDC( NULL ); // Use DIBSection for source hXORBitmap = CreateDIBSection( hDC, lpIcon->lpbi, DIB_RGB_COLORS, &pXORBits, NULL, 0 ); memcpy( pXORBits, lpIcon->lpXOR, (lpIcon->lpbi->bmiHeader.biHeight) * BytesPerLine((LPBITMAPINFOHEADER)(lpIcon->lpbi)) ); hMemDC1 = CreateCompatibleDC( hDC ); hOldXORBitmap = SelectObject( hMemDC1, hXORBitmap ); // Set the color table if need be if( lpIcon->lpbi->bmiHeader.biBitCount <= 8 ) SetDIBColorTable( hMemDC1, 0, DIBNumColors((LPSTR)(lpIcon->lpbi)), lpIcon->lpbi->bmiColors); // What's the transparent color? crTransparentColor = GetPixel( hMemDC1, pt.x, pt.y ); // Loop through the pixels for(i=0;i<lpIcon->lpbi->bmiHeader.biWidth;i++) { for(j=0;j<lpIcon->lpbi->bmiHeader.biHeight;j++) { // Is the source transparent at this point? if( GetPixel( hMemDC1, i, j ) == crTransparentColor ) { // Yes, so set the pixel in AND mask, and clear it in XOR mask SetMonoDIBPixel( lpIcon->lpAND, lpIcon->lpbi->bmiHeader.biWidth, lpIcon->lpbi->bmiHeader.biHeight, i, j, TRUE ); if( lpIcon->lpbi->bmiHeader.biBitCount == 1 ) SetMonoDIBPixel( pXORBits, lpIcon->lpbi->bmiHeader.biWidth, lpIcon->lpbi->bmiHeader.biHeight, i, j, FALSE ); else SetPixelV( hMemDC1, i, j, RGB(0,0,0) ); } else { // No, so clear pixel in AND mask SetMonoDIBPixel( lpIcon->lpAND, lpIcon->lpbi->bmiHeader.biWidth, lpIcon->lpbi->bmiHeader.biHeight, i, j, FALSE ); } } } // Flush the SetPixelV() calls GdiFlush(); SelectObject( hMemDC1, hOldXORBitmap ); // Copy the new XOR bits back to our storage memcpy( lpIcon->lpXOR, pXORBits, (lpIcon->lpbi->bmiHeader.biHeight) * BytesPerLine((LPBITMAPINFOHEADER)(lpIcon->lpbi)) ); // Clean up DeleteObject( hXORBitmap ); DeleteDC( hMemDC1 ); ReleaseDC( NULL, hDC ); // UnAccount for height*2 thing lpIcon->lpbi->bmiHeader.biHeight *= 2; return TRUE; }
BOOL CDIB::SetBitmap(HBITMAP hBitmap, HPALETTE hPal /*= NULL*/) { // DeleteObject(); if (!hBitmap) return FALSE; // Get dimensions of bitmap BITMAP bm; if (!::GetObject(hBitmap, sizeof(bm),(LPVOID)&bm)) return FALSE; bm.bmHeight = abs(bm.bmHeight); HDC hDC = GetWindowDC(NULL); HPALETTE hOldPal = NULL; m_iColorTableSize = NumColorEntries(bm.bmBitsPixel, BI_RGB); // Initialize the BITMAPINFOHEADER in m_DIBinfo BITMAPINFOHEADER& bih = m_DIBinfo.bmiHeader; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = bm.bmWidth; bih.biHeight = bm.bmHeight; bih.biPlanes = 1; // Must always be 1 according to docs bih.biBitCount = bm.bmBitsPixel; bih.biCompression = BI_RGB; bih.biSizeImage = BytesPerLine(bm.bmWidth, bm.bmBitsPixel) * bm.bmHeight; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0; GetColorTableEntries(hDC, hBitmap); // If we have a palette supplied, then set the palette (and hance DIB color // table) using this palette if (hPal) SetPalette(hPal); if (hPal) { hOldPal = SelectPalette(hDC, m_hPal, FALSE); RealizePalette(hDC); } // Create it! m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo, m_iColorDataType, &m_ppvBits, NULL, 0); if (hOldPal) SelectPalette(hDC, hOldPal, FALSE); hOldPal = NULL; if (! m_hBitmap) { TRACE0("Unable to CreateDIBSection\n"); return FALSE; } // If palette was supplied then create a palette using the entries in the DIB // color table. if (! hPal) CreatePalette(); // Need to copy the supplied bitmap onto the newly created DIBsection HDC hMemDC = CreateCompatibleDC(hDC); HDC hCopyDC = CreateCompatibleDC(hDC); if (! hMemDC || ! hCopyDC) { TRACE0("Unable to create compatible DC's\n"); //AfxThrowResourceException(); } if (m_hPal) { SelectPalette(hMemDC, m_hPal, FALSE); RealizePalette(hMemDC); SelectPalette(hCopyDC, m_hPal, FALSE); RealizePalette(hCopyDC); } HBITMAP hOldMemBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap); HBITMAP hOldCopyBitmap = (HBITMAP) SelectObject(hCopyDC, m_hBitmap); BitBlt(hCopyDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldMemBitmap); SelectObject(hCopyDC, hOldCopyBitmap); if (m_hPal) { HGDIOBJ hObj = ::GetStockObject(DEFAULT_PALETTE); SelectObject(hMemDC, hObj); SelectObject(hCopyDC, hObj); } ReleaseDC(NULL, hDC); return TRUE; }
/*! Rotate the current Dib on 90. At the first time a new dib is created an rotation is performed Attention: this function is not valid for 256 colors because no palette is loaded. OleLoadPicture make a bitmap and map each color on sistem color. For sistem with 256 colors or minor a palette is needed // \param RECT &rc : // \param HDC hdcDST : // \param HDC hdcSRC : */ BOOL CAxJpgCard::DrawRotated(RECT &rc, HDC hdcDST, HDC hdcSRC) { BITMAP bm; UINT iColorDataType; // color data type (palette or RGB values) if (!m_bCreatedRot) { // create a new rotated dib // bitmap pointer ::GetObject( m_hCurrentBitmap, sizeof(bm), (LPVOID)&bm ); // by LoadImage if create Dib is done, the pointer of the Bits is bm.Bits HDC hdcComp = CreateCompatibleDC(hdcSRC); iColorDataType = DIB_RGB_COLORS; // create rotated DIB DIBINFO DIBinfo; BITMAPINFOHEADER& bih = DIBinfo.bmiHeader; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = bm.bmHeight; bih.biHeight = bm.bmWidth ; bih.biPlanes = 1; // Must always be 1 according to docs bih.biBitCount = bm.bmBitsPixel; bih.biCompression = BI_RGB; bih.biSizeImage = BytesPerLine(bm.bmHeight, bm.bmBitsPixel) * bm.bmWidth; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0; //CDIBSectionLite Myth; //Myth.SetBitmap(m_hCurrentImage,NULL); // calls GetDIBits with NULL bits pointer to fill in the BITMAPINFOHEADER data // This filled DIBinfo is used to create the rotated DIB. We need this call because // we have no color information if (!::GetDIBits(hdcComp, m_hCurrentBitmap, 0, bm.bmHeight, NULL, DIBinfo, iColorDataType)) { ATLTRACE("Unable to GetDIBits\n"); } // invert width and height, invert now otherwise GetDIBits fail // source bitmap is very easy to retrive and this is a DIB bitmap, not a DDB BYTE* pvBitsSRC = (BYTE*)bm.bmBits; BYTE* pvBitsDST = NULL; // create dib for rotated image with bitmap set to all null HBITMAP hRotated = ::CreateDIBSection(hdcComp , (const BITMAPINFO*) DIBinfo, DIB_RGB_COLORS, (VOID**)&pvBitsDST, NULL, 0); ATLASSERT( hRotated != NULL); // copy the buffer int iBytePerLineDST = BytesPerLine(bm.bmHeight, bm.bmBitsPixel); int iBytePerLineSRC = BytesPerLine(bm.bmWidth, bm.bmBitsPixel); int iIndexDST = 0; int iIndexSRC = 0; int iIndexSRCNext = 0; int iIndexDSTNext = 0; int iWidthDST = bm.bmHeight; int iHeightDST = bm.bmWidth; int iWidthSRC = bm.bmWidth ; int iheightSRC = bm.bmHeight ; int iBitFactor = bm.bmBitsPixel / 8; // rotation on 90° on clock direction for (int i = 0; i < iheightSRC; i ++ ) { iIndexDST = i * iBitFactor + iBytePerLineDST * (iWidthSRC - 1); iIndexSRC = i * iBytePerLineSRC; for (int j = 0; j < iWidthSRC; j ++) { iIndexDSTNext = iIndexDST + 1; iIndexSRCNext = iIndexSRC + 1; if (iBitFactor > 2) { // true color int iDST3 = iIndexDSTNext + 1; int iSRC3 = iIndexSRCNext + 1; pvBitsDST[iDST3] = pvBitsSRC[iSRC3]; } ATLASSERT(iIndexDST >= 0); pvBitsDST[iIndexDST] = pvBitsSRC[iIndexSRC]; pvBitsDST[iIndexDSTNext] = pvBitsSRC[iIndexSRCNext]; iIndexDST -= iBytePerLineDST ; iIndexSRC += iBitFactor; } } // set the current image to rotated image m_hCurrentBitmap = hRotated; SelectObject(hdcComp, m_hCurrentBitmap); SetStretchBltMode(hdcDST, COLORONCOLOR); // blit the image StretchBlt(hdcDST, rc.left, rc.top, (rc.right - rc.left) , (rc.bottom - rc.top), hdcComp, 0,0, e_BmH,e_BmW, SRCCOPY ); DeleteDC(hdcComp); m_bCreatedRot = true; } else { SetStretchBltMode(hdcDST, COLORONCOLOR); // image is already created, only stretch on display StretchBlt(hdcDST, rc.left, rc.top, (rc.right - rc.left) , (rc.bottom - rc.top), hdcSRC, 0,0, e_BmH, e_BmW, SRCCOPY ); } return TRUE; }
/**************************************************************************** * * FUNCTION: ConvertDIBFormat * * PURPOSE: Creates a new DIB of the requested format, copies the source * image to the new DIB. * * PARAMS: LPBITMAPINFO lpSrcDIB - the source CF_DIB * UINT nWidth - width for new DIB * UINT nHeight - height for new DIB * UINT nbpp - bpp for new DIB * BOOL bStretch - TRUE to stretch source to dest * FALSE to take upper left of image * * RETURNS: LPBYTE - pointer to new CF_DIB memory block with new image * NULL on failure * * History: * July '95 - Created * \****************************************************************************/ LPBYTE ConvertDIBFormat( LPBITMAPINFO lpSrcDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch ) { LPBITMAPINFO lpbmi = NULL; LPBYTE lpSourceBits, lpTargetBits, lpResult; HDC hDC = NULL, hSourceDC, hTargetDC; HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; // Allocate and fill out a BITMAPINFO struct for the new DIB // Allow enough room for a 256-entry color table, just in case dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( 256 * sizeof( RGBQUAD ) ); lpbmi = malloc( dwTargetHeaderSize ); lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); lpbmi->bmiHeader.biWidth = nWidth; lpbmi->bmiHeader.biHeight = nHeight; lpbmi->bmiHeader.biPlanes = 1; lpbmi->bmiHeader.biBitCount = nbpp; lpbmi->bmiHeader.biCompression = BI_RGB; lpbmi->bmiHeader.biSizeImage = 0; lpbmi->bmiHeader.biXPelsPerMeter = 0; lpbmi->bmiHeader.biYPelsPerMeter = 0; lpbmi->bmiHeader.biClrUsed = 0; lpbmi->bmiHeader.biClrImportant = 0; // Fill in the color table if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB ) ) { free( lpbmi ); return NULL; } // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em hDC = GetDC( NULL ); hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, &lpTargetBits, NULL, 0 ); hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, &lpSourceBits, NULL, 0 ); hSourceDC = CreateCompatibleDC( hDC ); hTargetDC = CreateCompatibleDC( hDC ); // Flip the bits on the source DIBSection to match the source DIB dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine(&(lpSrcDIB->bmiHeader)); dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine(&(lpbmi->bmiHeader)); memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); // Select DIBSections into DCs hOldSourceBitmap = SelectObject( hSourceDC, hSourceBitmap ); hOldTargetBitmap = SelectObject( hTargetDC, hTargetBitmap ); // Set the color tables for the DIBSections if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); if( lpbmi->bmiHeader.biBitCount <= 8 ) SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); // If we are asking for a straight copy, do it if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) ) { BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); } else { // else, should we stretch it? if( bStretch ) { SetStretchBltMode( hTargetDC, COLORONCOLOR ); StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY ); } else { // or just take the upper left corner of the source BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); } } // Clean up and delete the DCs SelectObject( hSourceDC, hOldSourceBitmap ); SelectObject( hSourceDC, hOldTargetBitmap ); DeleteDC( hSourceDC ); DeleteDC( hTargetDC ); ReleaseDC( NULL, hDC ); // Flush the GDI batch, so we can play with the bits GdiFlush(); // Allocate enough memory for the new CF_DIB, and copy bits lpResult = malloc( dwTargetHeaderSize + dwTargetBitsSize ); memcpy( lpResult, lpbmi, dwTargetHeaderSize ); memcpy( FindDIBBits( lpResult ), lpTargetBits, dwTargetBitsSize ); // final cleanup DeleteObject( hTargetBitmap ); DeleteObject( hSourceBitmap ); free( lpbmi ); return lpResult; }
/**************************************************************************** * * FUNCTION: ReadBMPFile * * PURPOSE: Reads a BMP file into CF_DIB format * * PARAMS: LPCTSTR szFileName - the name of the file to read * * RETURNS: LPBYTE - pointer to the CF_DIB, NULL for failure * * History: * July '95 - Created * \****************************************************************************/ LPBYTE ReadBMPFile( LPCTSTR szFileName ) { HANDLE hFile; BITMAPFILEHEADER bfh; DWORD dwBytes; LPBYTE lpDIB = NULL, lpTemp = NULL; WORD wPaletteSize = 0; DWORD dwBitsSize = 0; // Open the file if( (hFile=CreateFile( szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE ) { MessageBox( NULL, "Error opening file", szFileName, MB_OK ); return NULL; } // Read the header if( ( ! ReadFile( hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwBytes, NULL ) ) || ( dwBytes != sizeof( BITMAPFILEHEADER ) ) ) { CloseHandle( hFile ); MessageBox( NULL, "Error reading file", szFileName, MB_OK ); return NULL; } // Does it look like a BMP file? if( ( bfh.bfType != 0x4d42 ) || (bfh.bfReserved1!=0) || (bfh.bfReserved2!=0) ) { CloseHandle( hFile ); MessageBox( NULL, "Not a recognised BMP format file", szFileName, MB_OK ); return NULL; } // Allocate some memory if( (lpDIB = malloc( sizeof( BITMAPINFO ) )) == NULL ) { CloseHandle( hFile ); MessageBox( NULL, "Failed to allocate memory for DIB", szFileName, MB_OK ); return NULL; } // Read in the BITMAPINFOHEADER if( (!ReadFile( hFile, lpDIB, sizeof(BITMAPINFOHEADER), &dwBytes, NULL )) || (dwBytes!=sizeof(BITMAPINFOHEADER)) ) { CloseHandle( hFile ); free( lpDIB ); MessageBox( NULL, "Error reading file", szFileName, MB_OK ); return NULL; } if( ((LPBITMAPINFOHEADER)lpDIB)->biSize != sizeof( BITMAPINFOHEADER ) ) { CloseHandle( hFile ); free( lpDIB ); MessageBox( NULL, "OS/2 style BMPs Not Supported", szFileName, MB_OK ); return NULL; } // How big are the elements? wPaletteSize = PaletteSize((LPSTR)lpDIB); dwBitsSize = ((LPBITMAPINFOHEADER)lpDIB)->biHeight * BytesPerLine((LPBITMAPINFOHEADER)lpDIB); // realloc to account for the total size of the DIB if( (lpTemp = realloc( lpDIB, sizeof( BITMAPINFOHEADER ) + wPaletteSize + dwBitsSize )) == NULL ) { CloseHandle( hFile ); MessageBox( NULL, "Failed to allocate memory for DIB", szFileName, MB_OK ); free( lpDIB ); return NULL; } lpDIB = lpTemp; // If there is a color table, read it if( wPaletteSize != 0 ) { if( (!ReadFile( hFile, ((LPBITMAPINFO)lpDIB)->bmiColors, wPaletteSize, &dwBytes, NULL )) || (dwBytes!=wPaletteSize) ) { CloseHandle( hFile ); free( lpDIB ); MessageBox( NULL, "Error reading file", szFileName, MB_OK ); return NULL; } } // Seek to the bits // checking against 0 in case some bogus app didn't set this element if( bfh.bfOffBits != 0 ) { if( SetFilePointer( hFile, bfh.bfOffBits, NULL, FILE_BEGIN ) == 0xffffffff ) { CloseHandle( hFile ); free( lpDIB ); MessageBox( NULL, "Error reading file", szFileName, MB_OK ); return NULL; } } // Read the image bits if( (!ReadFile( hFile, FindDIBBits(lpDIB), dwBitsSize, &dwBytes, NULL )) || (dwBytes!=dwBitsSize) ) { CloseHandle( hFile ); free( lpDIB ); MessageBox( NULL, "Error reading file", szFileName, MB_OK ); return NULL; } // clean up CloseHandle( hFile ); return lpDIB; }
/************************************************************************* * * DilationDIB() * * Parameters: * * HDIB hDib - objective DIB handle * BOOL bHori - dilation direction * * Return Value: * * BOOL - True is success, else False * * Description: * * This function do dilation with the specified direction * ************************************************************************/ BOOL DilationDIB(HDIB hDib, BOOL bHori) { // start wait cursor WaitCursorBegin(); // Old DIB buffer if (hDib == NULL) { WaitCursorEnd(); return FALSE; } // only support 256 color image WORD wBitCount = DIBBitCount(hDib); if (wBitCount != 8) { WaitCursorEnd(); return FALSE; } // new DIB HDIB hNewDIB = CopyHandle(hDib); if (! hNewDIB) { WaitCursorEnd(); return FALSE; } // source dib buffer LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib); if (! lpSrcDIB) { WaitCursorBegin(); return FALSE; } // New DIB buffer LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB); if (! lpbmi) { WaitCursorBegin(); return FALSE; } // start erosion... LPSTR lpPtr; LPSTR lpTempPtr; LONG x,y; BYTE num, num0; int i; LONG lHeight = DIBHeight(lpSrcDIB); LONG lWidth = DIBWidth(lpSrcDIB); DWORD dwBufferSize = GlobalSize(lpSrcDIB); int nLineBytes = BytesPerLine(lpSrcDIB); if(bHori) { for(y=0;y<lHeight;y++) { lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes)+1; lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes)+1; for(x=1;x<lWidth-1;x++) { num0 = num = 255; for(i=0;i<3;i++) { num=(unsigned char)*(lpPtr+i-1); if(num < num0) num0 = num; } *lpTempPtr=(unsigned char)num0; /* num=(unsigned char)*lpPtr; if (num==255) { *lpTempPtr=(unsigned char)255; for(i=0;i<3;i++) { num=(unsigned char)*(lpPtr+i-1); if(num==0) { *lpTempPtr=(unsigned char)0; break; } } } else *lpTempPtr=(unsigned char)0; */ lpPtr++; lpTempPtr++; } } } else { for(y=1;y<lHeight-1;y++) { lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes); lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes); for(x=0;x<lWidth;x++) { num0 = num = 255; for(i=0;i<3;i++) { num=(unsigned char)*(lpPtr+i-1); if(num < num0) num0 = num; } *lpTempPtr=(unsigned char)num0; /* num=(unsigned char)*lpPtr; if (num==255) { *lpTempPtr=(unsigned char)255; for(i=0;i<3;i++) { num=(unsigned char)*(lpPtr+(i-1)*nLineBytes); if(num==0) { *lpTempPtr=(unsigned char)0; break; } } } else *lpTempPtr=(unsigned char)0; */ lpPtr++; lpTempPtr++; } } } // cleanup GlobalUnlock(hDib); GlobalUnlock(hNewDIB); GlobalFree(hNewDIB); WaitCursorEnd(); return TRUE; }
//******************* 保存为PCX (由CDib对象) *********************** BOOL LanImage::SavePcx(LPCTSTR lpstrFileName, CDib* pDib) { int i = 0; if (pDib == NULL) return FALSE; HDIB hDib = CopyHandle(pDib->GetHandle()); if (hDib == NULL) return FALSE; CDib* pDibTmp = new CDib(); pDibTmp->Attach(hDib); UINT uWidth = pDibTmp->GetWidth(); UINT uHeight = pDibTmp->GetHeight(); // 当打开的图像BitCount不为8时,转为8位格式 if (pDibTmp->GetBitCount() != 8) pDibTmp->ConvertFormat(8); // make PCX header PCXHEAD header; memset((LPBYTE)&header, 0, sizeof(PCXHEAD)); header.manufacturer = 0x0A; header.version = 5; header.encoding = 1; header.bit_per_pixel = 8; //header.bit_per_pixel = 24; header.xmin = 0; header.ymin = 0; header.xmax = uWidth-1; header.ymax = uHeight-1; //header.Xresolution; //header.Yresolution; header.palette[0] = (BYTE)0x00; // for correct process for mono header.palette[1] = (BYTE)0x00; header.palette[2] = (BYTE)0x00; header.palette[3] = (BYTE)0xff; header.palette[4] = (BYTE)0xff; header.palette[5] = (BYTE)0xff; //header.palette[48]; header.reserved = 0; header.color_planes = 1; header.byte_per_line = uWidth; header.palette_type = 1; //filler[58]; // construct PCX palette from DIB color table PCXPALETTE palette[256]; PALETTEENTRY PaletteColors[256]; pDibTmp->GetPalette()->GetPaletteEntries(0, 256, PaletteColors); for (i=0;i<256;i++) { palette[i].rgbRed = PaletteColors[i].peRed; palette[i].rgbGreen = PaletteColors[i].peGreen; palette[i].rgbBlue = PaletteColors[i].peBlue; } // get bits ptr HDIB hDIB = CopyHandle(pDibTmp->GetHandle()); delete pDibTmp; LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); BYTE* lpBuffer = (BYTE *)FindDIBBits(lpDIB); WORD wWidthBytes = (WORD)BytesPerLine(lpDIB); /*** Open the PCX file ***/ FILE *outFile; if ((outFile=fopen(lpstrFileName,"wb")) == NULL) { GlobalUnlock(hDIB); GlobalFree(hDIB); return FALSE; } /*** Write the header ***/ fwrite((char *)&header, sizeof(PCXHEAD), 1, outFile); /*** Write image data ***/ for ( i=(int)uHeight-1; i>=0; --i) { if (! WritePCXLine(header.byte_per_line, lpBuffer+i*wWidthBytes, outFile)) { fclose(outFile); GlobalUnlock(hDIB); GlobalFree(hDIB); return FALSE; } } /*** Write the palette data ***/ fputc(0x0c, outFile); fwrite((char *)palette, 1, sizeof(palette), outFile); // clear & close fclose(outFile); GlobalUnlock(hDIB); GlobalFree(hDIB); return TRUE; }
/************************************************************************* * * ConvoluteDIB() * * Parameters: * * HDIB hDib - objective DIB handle * KERNEL *lpKernel - pointer of kernel used to convolute with DIB * int Strength - operation strength set to the convolute * int nKernelNum - kernel number used to convolute * * Return Value: * * BOOL - True is success, else False * * Description: * * This is the generic convolute function to DIB * ************************************************************************/ BOOL ConvoluteDIB(HDIB hDib, KERNEL *lpKernel, int Strength, int nKernelNum) { WaitCursorBegin(); HDIB hNewDib = NULL; // we only convolute 24bpp DIB, so first convert DIB to 24bpp WORD wBitCount = DIBBitCount(hDib); if (wBitCount != 24) hNewDib = ConvertDIBFormat(hDib, 24, NULL); else hNewDib = CopyHandle(hDib); if (! hNewDib) { WaitCursorEnd(); return FALSE; } // new DIB attributes WORD wDIBWidth = (WORD)DIBWidth(hNewDib); WORD wDIBHeight = (WORD)DIBHeight(hNewDib); WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib); DWORD dwImageSize = wBytesPerLine * wDIBHeight; // Allocate and lock memory for filtered image data HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize); if (!hFilteredBits) { WaitCursorEnd(); return FALSE; } LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits); // get bits address in DIB LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); LPBYTE lpDIBits = FindDIBBits(lpDIB); // convolute... for (int i=1; i<wDIBHeight-1; i++) for (int j=1; j<wDIBWidth-1; j++) { int red=0, green=0, blue=0; for (int k=0; k<nKernelNum; ++k) { int r=0, g=0, b=0; DoConvoluteDIB(&r, &g, &b, i, j, wBytesPerLine, lpDIBits, lpKernel+k); if (r > red) red = r; if (g > green) green = g; if (b > blue) blue = b; //red += r; green += g; blue += b; } // original RGB value in center pixel (j, i) LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); BYTE OldB = *(lpDIBits + lOffset++); BYTE OldG = *(lpDIBits + lOffset++); BYTE OldR = *(lpDIBits + lOffset); // When we get here, red, green and blue have the new RGB value. if (Strength != 10) { // Interpolate pixel data red = OldR + (((red - OldR) * Strength) / 10); green = OldG + (((green - OldG) * Strength) / 10); blue = OldB + (((blue - OldB) * Strength) / 10); } lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); *(lpDestImage + lOffset++) = BOUND(blue, 0, 255); *(lpDestImage + lOffset++) = BOUND(green, 0, 255); *(lpDestImage + lOffset) = BOUND(red, 0, 255); } // a filtered image is available in lpDestImage // copy it to DIB bits memcpy(lpDIBits, lpDestImage, dwImageSize); // cleanup temp buffers GlobalUnlock(hFilteredBits); GlobalFree(hFilteredBits); GlobalUnlock(hNewDib); // rebuild hDib HDIB hTmp = NULL; if (wBitCount != 24) hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL); else hTmp = CopyHandle(hNewDib); GlobalFree(hNewDib); DWORD dwSize = GlobalSize(hTmp); memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize); GlobalUnlock(hTmp); GlobalFree(hTmp); GlobalUnlock(hDib); WaitCursorEnd(); return TRUE; }
/************************************************************************* * * MedianFilterDIB() * * Parameters: * * HDIB hDib - objective DIB handle * * Return Value: * * BOOL - True is success, else False * * Description: * * This is the media filtering function to DIB * ************************************************************************/ BOOL MedianFilterDIB(HDIB hDib) { WaitCursorBegin(); HDIB hNewDib = NULL; // we only convolute 24bpp DIB, so first convert DIB to 24bpp WORD wBitCount = DIBBitCount(hDib); if (wBitCount != 24) hNewDib = ConvertDIBFormat(hDib, 24, NULL); else hNewDib = CopyHandle(hDib); if (! hNewDib) { WaitCursorEnd(); return FALSE; } // new DIB attributes WORD wDIBWidth = (WORD)DIBWidth(hNewDib); WORD wDIBHeight = (WORD)DIBHeight(hNewDib); WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib); DWORD dwImageSize = wBytesPerLine * wDIBHeight; // Allocate and lock memory for filtered image data HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize); if (!hFilteredBits) { WaitCursorEnd(); return FALSE; } LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits); // get bits address in DIB LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); LPBYTE lpDIBits = FindDIBBits(lpDIB); // convolute... for (int i=1; i<wDIBHeight-1; i++) for (int j=1; j<wDIBWidth-1; j++) { int red=0, green=0, blue=0; DoMedianFilterDIB(&red, &green, &blue, i, j, wBytesPerLine, lpDIBits); LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); *(lpDestImage + lOffset++) = BOUND(blue, 0, 255); *(lpDestImage + lOffset++) = BOUND(green, 0, 255); *(lpDestImage + lOffset) = BOUND(red, 0, 255); } // a filtered image is available in lpDestImage // copy it to DIB bits memcpy(lpDIBits, lpDestImage, dwImageSize); // cleanup temp buffers GlobalUnlock(hFilteredBits); GlobalFree(hFilteredBits); GlobalUnlock(hNewDib); // rebuild hDib HDIB hTmp = NULL; if (wBitCount != 24) hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL); else hTmp = CopyHandle(hNewDib); GlobalFree(hNewDib); DWORD dwSize = GlobalSize(hTmp); memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize); GlobalUnlock(hTmp); GlobalFree(hTmp); GlobalUnlock(hDib); WaitCursorEnd(); return TRUE; }
/************************************************************************* * * ThinningDIB() * * Parameters: * * HDIB hDib - objective DIB handle * * Return Value: * * BOOL - True is success, else False * * Description: * * This function thins a DIB * ************************************************************************/ BOOL ThinningDIB(HDIB hDib) { static int erasetable[256]= { 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1, 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1, 1,1,0,0,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,0,0, 1,1,0,1,1,1,0,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1, 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,0,0, 1,1,0,1,1,1,0,0, 1,1,0,0,1,1,1,0, 1,1,0,0,1,0,0,0 }; // start wait cursor WaitCursorBegin(); // Old DIB buffer if (hDib == NULL) { WaitCursorEnd(); return FALSE; } // only support 256 color image WORD wBitCount = DIBBitCount(hDib); if (wBitCount != 8) { WaitCursorEnd(); return FALSE; } // new DIB HDIB hNewDIB = CopyHandle(hDib); if (! hNewDIB) { WaitCursorEnd(); return FALSE; } // source dib buffer LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib); if (! lpSrcDIB) { WaitCursorBegin(); return FALSE; } // New DIB buffer LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB); if (! lpbmi) { WaitCursorBegin(); return FALSE; } // start erosion... LPSTR lpPtr; LPSTR lpTempPtr; LONG x,y; BYTE num; LONG lHeight = DIBHeight(lpSrcDIB); LONG lWidth = DIBWidth(lpSrcDIB); DWORD dwBufferSize = GlobalSize(lpSrcDIB); int nLineBytes = BytesPerLine(lpSrcDIB); int nw,n,ne,w,e,sw,s,se; BOOL Finished=FALSE; while(!Finished) { Finished=TRUE; for (y=1;y<lHeight-1;y++) { lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes); lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes); x=1; while(x<lWidth-1) { if(*(lpPtr+x)==0) { w=(unsigned char)*(lpPtr+x-1); e=(unsigned char)*(lpPtr+x+1); if( (w==255)|| (e==255)) { nw=(unsigned char)*(lpPtr+x+nLineBytes-1); n=(unsigned char)*(lpPtr+x+nLineBytes); ne=(unsigned char)*(lpPtr+x+nLineBytes+1); sw=(unsigned char)*(lpPtr+x-nLineBytes-1); s=(unsigned char)*(lpPtr+x-nLineBytes); se=(unsigned char)*(lpPtr+x-nLineBytes+1); num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128; if(erasetable[num]==1) { *(lpPtr+x)=(BYTE)255; *(lpTempPtr+x)=(BYTE)255; Finished=FALSE; x++; } } } x++; } } for (x=1;x<lWidth-1;x++) { y=1; while(y<lHeight-1) { lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes); lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes); if(*(lpPtr+x)==0) { n=(unsigned char)*(lpPtr+x+nLineBytes); s=(unsigned char)*(lpPtr+x-nLineBytes); if( (n==255)|| (s==255)) { nw=(unsigned char)*(lpPtr+x+nLineBytes-1); ne=(unsigned char)*(lpPtr+x+nLineBytes+1); w=(unsigned char)*(lpPtr+x-1); e=(unsigned char)*(lpPtr+x+1); sw=(unsigned char)*(lpPtr+x-nLineBytes-1); se=(unsigned char)*(lpPtr+x-nLineBytes+1); num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128; if(erasetable[num]==1) { *(lpPtr+x)=(BYTE)255; *(lpTempPtr+x)=(BYTE)255; Finished=FALSE; y++; } } } y++; } } } // cleanup GlobalUnlock(hDib); GlobalUnlock(hNewDIB); GlobalFree(hNewDIB); return TRUE; }