Пример #1
0
bool CPicShowCtrl::SaveFile(CString strPath)
{
	int width=180;
	int height=180;

	CPaintDC dc(this);
	CxImage img;
	img.CreateFromHBITMAP(m_hBmp);

	CBitmap bitmapmem;          
	CBitmap *pOldBit;
	CDC m_pMemDC;
	m_pMemDC.CreateCompatibleDC(&dc); 
	bitmapmem.CreateCompatibleBitmap(&dc, width, height);
	pOldBit=m_pMemDC.SelectObject(&bitmapmem);

	CRect rect(0,0,width,height);
	HBRUSH bgBrush = ::CreateSolidBrush(RGB(255,255,255));
	FillRect(m_pMemDC,&rect,bgBrush);
	DeleteObject(bgBrush);
	img.Draw(m_pMemDC,m_iStartx,m_iStarty,img.GetWidth(),img.GetHeight(),&rect);

	CBitmap* pBmp=m_pMemDC.SelectObject(pOldBit);

	CxImage xImagebmp;
	xImagebmp.CreateFromHBITMAP((HBITMAP)bitmapmem.m_hObject);
	xImagebmp.Resample(100,100,0);  
	bitmapmem.DeleteObject();
	m_pMemDC.DeleteDC();
	if(xImagebmp.Save(common::utility::stringhelper::UnicodeToAscii(strPath.GetBuffer()).c_str(), CXIMAGE_FORMAT_JPG))
	{
		return true;
	}
	return false;
}
Пример #2
0
    HBITMAP MixBitmap(HBITMAP hDstMix, HBITMAP hSrcMix, LONG xOffset, LONG yOffset)
    {
        CxImage ximage;
        ximage.CreateFromHBITMAP(hDstMix);
        ximage.IncreaseBpp(24);

        CxImage ximageStatus;
        ximageStatus.CreateFromHBITMAP(hSrcMix);

        ximage.MixFrom(ximageStatus, xOffset, yOffset);

        return ximage.MakeBitmap();
    }
Пример #3
0
BOOL ScreenSnapshot::saveRect(__in RECT &rc, __in std::wstring &savePath)
{
	snapshotScreen();

	CxImage img;
	int cx = rc.right - rc.left;
	int cy = rc.bottom - rc.top;

	HDC hSaveDC = CreateCompatibleDC(m_hMemDC);
	HBITMAP hBitmap = CreateCompatibleBitmap(m_hMemDC, cx, cy);
	HBITMAP hSaveBitmap = (HBITMAP)SelectObject(hSaveDC, (HGDIOBJ)hBitmap);
	BitBlt(hSaveDC, 0, 0, cx, cy, m_hMemDC, rc.left, rc.top, SRCCOPY);
	hBitmap = (HBITMAP)SelectObject(hSaveDC, (HBITMAP)hSaveBitmap);
	
	BOOL result = FALSE;
	do 
	{
		if (!img.CreateFromHBITMAP(hBitmap))
		{
			break;
		}
		if (!img.Save(savePath.c_str(), CXIMAGE_FORMAT_BMP))
		{
			break;
		}
		result = TRUE;
	} while (FALSE);

	DeleteObject((HGDIOBJ)hBitmap);
	DeleteDC(hSaveDC);

	return result;
}
Пример #4
0
    HBITMAP FrameBitmap(HBITMAP hBmp, COLORREF clrInColor, COLORREF clrOutColor, UINT inLineWidth, UINT outLineWidth)
    {
        CxImage ximage;
        ximage.CreateFromHBITMAP(hBmp);
        ximage.IncreaseBpp(24);

        UINT totalWidth = inLineWidth + outLineWidth;
        if (totalWidth == 0)
            return ximage.MakeBitmap();

        LONG newWidth = ximage.GetWidth() + totalWidth * 2;
        LONG newHeight = ximage.GetHeight() + totalWidth * 2;

        RGBQUAD expandClr;
        expandClr.rgbBlue = GetBValue(clrInColor);
        expandClr.rgbGreen = GetGValue(clrInColor);
        expandClr.rgbRed = GetRValue(clrInColor);
        expandClr.rgbReserved = 0;
        ximage.Expand(newWidth, newHeight, expandClr);

        ximage.DrawLine(1, (newWidth - 1), 1, 1, clrOutColor);
        ximage.DrawLine(1, 1, 1, (newHeight - 1), clrOutColor);
        ximage.DrawLine((newWidth - 1), (newWidth - 1), 1, (newHeight - 1), clrOutColor);
        ximage.DrawLine((newWidth - 1), 1, (newHeight - 1), (newHeight - 1), clrOutColor);

        return ximage.MakeBitmap();
    }
Пример #5
0
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
bool CapturedImage::Get(CxImage& image) {
	bool ret = false;

	if (_bitmap_handle)
		ret = image.CreateFromHBITMAP(_bitmap_handle);

	return ret;
}
Пример #6
0
void CxImage::CreateFromHICON(HICON hico)
{
	Destroy();
	if (hico) { 
		ICONINFO iinfo;
		GetIconInfo(hico,&iinfo);
		CreateFromHBITMAP(iinfo.hbmColor);
#if CXIMAGE_SUPPORT_ALPHA
		CxImage mask;
		mask.CreateFromHBITMAP(iinfo.hbmMask);
		mask.GrayScale();
		mask.Negative();
		AlphaSet(mask);
#endif
    }
}
Пример #7
0
void CPicShowCtrl::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	common::ui::CClientRect rcThis(this);
	if (m_hBmp == NULL)
	{
		//还没有选择图片,则绘制白色背景
		HBRUSH bgBrush = ::CreateSolidBrush(RGB(255,255,255));
		CRect rect;
		GetWindowRect(&rcThis);
		ScreenToClient(&rcThis);
		FillRect(dc,&rcThis,bgBrush);
		::DeleteObject(bgBrush);
	}
	else
	{
		int width=180;
		int height=180;

		CxImage img;
		img.CreateFromHBITMAP(m_hBmp);

		CBitmap bitmapmem;          
		CBitmap *pOldBit;
		CDC m_pMemDC;
		m_pMemDC.CreateCompatibleDC(&dc); 
		bitmapmem.CreateCompatibleBitmap(&dc, width, height);
		pOldBit=m_pMemDC.SelectObject(&bitmapmem);

		CRect rect(0,0,width,height);
		HBRUSH bgBrush = ::CreateSolidBrush(RGB(255,255,255));
		FillRect(m_pMemDC,&rect,bgBrush);
		DeleteObject(bgBrush);

		img.Draw(m_pMemDC,m_iStartx,m_iStarty,img.GetWidth(),img.GetHeight(),&rect);
		dc.SetStretchBltMode(HALFTONE);
		dc.StretchBlt(rcThis.left,rcThis.top,rcThis.Width(),rcThis.Height(),&m_pMemDC,0,0,width,height,SRCCOPY);
		m_pMemDC.SelectObject(pOldBit);
		m_pMemDC.DeleteDC();
		bitmapmem.DeleteObject();
	}
}
Пример #8
0
BOOL UIIMEdit::_SaveFile(IN HBITMAP hbitmap, OUT CString& strFilePath)
{
	SYSTEMTIME st = { 0 };
	GetLocalTime(&st);
	CString strTime;
	strTime.Format(_T("%d-%02d-%02d-%02d%02d%02d-%03d"), st.wYear,
		st.wMonth,
		st.wDay,
		st.wHour,
		st.wMinute,
		st.wSecond,
		st.wMilliseconds);
	util::createAllDirectories(module::getMiscModule()->getUserTempDir());
	CString csDstFileName = module::getMiscModule()->getUserTempDir() + strTime;
	CString csExtName = _T(".jpg");
	CxImage cximage;
	cximage.CreateFromHBITMAP(hbitmap);
	if (cximage.Save(csDstFileName + csExtName, CXIMAGE_FORMAT_JPG))
	{
		strFilePath = csDstFileName + csExtName;
		return TRUE;
	}
	return FALSE;
}
Пример #9
0
void CMainFrame::OnFileCapture() 
{
	DlgCapture dlg;
	if (dlg.DoModal()==IDOK){
		// get the desired window from dialog box
		HWND hwnd=dlg.m_SelectedWnd;
		// get window size
		CRect r;
		::GetWindowRect(hwnd,&r);

		int xScreen,yScreen;	//check if the window is out of the screen or maximixed <Qiang>
		int xshift = 0, yshift = 0;
		xScreen = GetSystemMetrics(SM_CXSCREEN);
		yScreen = GetSystemMetrics(SM_CYSCREEN);
		if(r.right > xScreen)
			   r.right = xScreen;
		if(r.bottom > yScreen)
			   r.bottom = yScreen;
		if(r.left < 0){
			   xshift = -r.left;
			   r.left = 0;
		}
		if(r.top < 0){
			   yshift = -r.top;
			   r.top = 0;
		}
		
		CSize sz(r.Width(), r.Height());
		if(sz.cx <= 0 || sz.cy <= 0) return;

		// bring the window at the top most level
		::SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

		// prepare the DCs
		HDC dstDC = ::GetDC(NULL);
        HDC srcDC = ::GetWindowDC(hwnd); //full window (::GetDC(hwnd); = clientarea)
		HDC memDC = ::CreateCompatibleDC(dstDC);
		
		// copy the screen to the bitmap
		HBITMAP bm =::CreateCompatibleBitmap(dstDC, sz.cx, sz.cy);
		HBITMAP oldbm = (HBITMAP)::SelectObject(memDC,bm);
		::BitBlt(memDC, 0, 0, sz.cx, sz.cy, srcDC, xshift, yshift, SRCCOPY);
	
		// restore the position
		::SetWindowPos(hwnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
		::SetWindowPos(m_hWnd,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

		// prepare the new document
		CDemoDoc *NewDoc=(CDemoDoc*)((CDemoApp*)AfxGetApp())->demoTemplate->OpenDocumentFile(NULL); 
		if (NewDoc)	{
			CxImage *newima = new CxImage();
			newima->CreateFromHBITMAP(bm);
			NewDoc->image = newima;
			CString s;
			s.Format(_T("Captured Image %d"),((CDemoApp*)AfxGetApp())->m_nDocCount++);
			NewDoc->SetTitle(s);
			NewDoc->UpdateAllViews(0,WM_USER_NEWIMAGE);
			NewDoc->UpdateStatusBar();
		}

		// free objects
		DeleteObject(SelectObject(memDC,oldbm));
		DeleteObject(memDC);
	}
}
Пример #10
0
BOOL CSonicImage::Rotate(int nAngle, POINT * pScout /* = NULL */)
{
	if(m_Dib.IsValid() == FALSE)
	{
		return FALSE;
	}
	nAngle = abs(nAngle) % 360;
	int nBitX = nAngle <= 180 ? 1 : 0;
	int nBitY = nAngle > 90 && nAngle <= 270 ? 1 : 0;
	int nSrcW = m_nWidth;
	int nSrcH = m_nHeight;
	const int nBytePixel = 4;
	BYTE * pSrc = m_Dib.GetBits();
	int nNewX = (nSrcW - nBitX) >> 1;
	int nNewY = (nSrcH - nBitY) >> 1;

	double m1 = -nSrcW / 2.0f;
	double m2 = nSrcW / 2.0f;
	double n1 = nSrcH / 2.0f;
	double n2 = -nSrcH / 2.0f;

	POINT pt1 = {(int)(m1 * COS(nAngle) + n1 * SIN(nAngle)) >> 10, (int)(-m1 * SIN(nAngle) + n1 * COS(nAngle)) >> 10};
	POINT pt2 = {(int)(m2 * COS(nAngle) + n1 * SIN(nAngle)) >> 10, (int)(-m2 * SIN(nAngle) + n1 * COS(nAngle)) >> 10};
	POINT pt3 = {(int)(m2 * COS(nAngle) + n2 * SIN(nAngle)) >> 10, (int)(-m2 * SIN(nAngle) + n2 * COS(nAngle)) >> 10};
	POINT pt4 = {(int)(m1 * COS(nAngle) + n2 * SIN(nAngle)) >> 10, (int)(-m1 * SIN(nAngle) + n2 * COS(nAngle)) >> 10};

	int i, j, x1, y1, x11, y11;
	i = abs(pt3.x - pt1.x);
	j = abs(pt4.x - pt2.x);
	int nDestW = max(i, j);
	i = abs(pt3.y - pt1.y);
	j = abs(pt4.y - pt2.y);
	int nDestH = max(i, j);

	m_nWidth = nDestW;
	m_nHeight = nDestH;
	HBITMAP hBmp = NULL;
	m_Dib.Resize(m_nWidth, m_nHeight, &hBmp);
	BYTE * pDest = m_Dib.GetBits();
	
	int temp;
	int nOriginX = nDestW >> 1;
	int nOriginY = nDestH >> 1;

	for(i = 0; i < nDestH; i++)
	{
		for(j = 0; j < nDestW; j++)
		{
			x1 = j - nOriginX;
			y1 = nOriginY - i;

			temp = (x1 * COS(nAngle) + y1 * SIN(nAngle)) >> 10;
			x11 = temp + nNewX;
			temp = (-x1 * SIN(nAngle) + y1 * COS(nAngle)) >> 10;
			y11 = nNewY - temp;
			if(x11 >= 0 && x11 < nSrcW && y11 >= 0 && y11 < nSrcH)
			{
				COLORREF color = *(DWORD *)(pSrc + (nSrcW * nBytePixel * y11) + x11 * nBytePixel);
				*(DWORD *)(pDest + i * nBytePixel * nDestW + j * nBytePixel) = color;
			}
		}
	}
	if(hBmp)
	{
		DeleteObject(hBmp);
	}
	if(pScout)
	{
		x1 = pScout->x - nNewX;
		y1 = nNewY - pScout->y;
        nAngle = 360 - nAngle;
		x11 = (x1 * COS(nAngle) + y1 * SIN(nAngle)) >> 10;
		x11 = x11 + nOriginX;
		y11 = (-x1 * SIN(nAngle) + y1 * COS(nAngle)) >> 10;
		y11 = nOriginY - y11;
		pScout->x = x11;
		pScout->y = y11;
	}
	EnableAlphaChannel(FALSE);
	return TRUE;
}

BOOL CSonicImage::SaveAsFile(LPCTSTR lpszFileName, enImageType imgType, int nQuality /* = 0 */)
{
	if(m_Dib.IsValid() == FALSE)
	{
		return FALSE;
	}
	CxImage img;

	if(img.CreateFromHBITMAP(m_Dib.GetHBitmap()) == FALSE)
	{
		return FALSE;
	}
	if(IsAlphaChannelValid()
		&& (imgType == IMAGE_TYPE_BMP
		|| imgType == IMAGE_TYPE_PNG
		|| imgType == IMAGE_TYPE_TGA
		|| imgType == IMAGE_TYPE_ICO))
	{
		img.AlphaCreate();
		for(int i = 0; i < m_nHeight; i++)
		{
			for(int j = 0; j < m_nWidth; j++)
			{
				BYTE bAlpha = *(m_Dib.GetBits() + i * m_nWidth * 4 + j * 4 + 3);
				img.AlphaSet(j, i, bAlpha);
			}
		}
	}
	DWORD dwType = 0;
	switch (imgType)
	{
	case IMAGE_TYPE_BMP:
		dwType = CXIMAGE_FORMAT_BMP;
		break;
	case IMAGE_TYPE_JPEG:
		dwType = CXIMAGE_FORMAT_JPG;
		nQuality = nQuality ? nQuality : DEFAULT_JPEG_QULITY;
		img.SetJpegQuality(nQuality);
		break;
	case IMAGE_TYPE_TGA:
		dwType = CXIMAGE_FORMAT_TGA;
		break;
	case IMAGE_TYPE_PNG:
		dwType = CXIMAGE_FORMAT_PNG;
		break;
	case IMAGE_TYPE_ICO:
		dwType = CXIMAGE_FORMAT_ICO;
		break;
	}
	CString strPath = lpszFileName;
	int nFind1 = strPath.ReverseFind(_T('\\'));
	int nFind2 = strPath.ReverseFind(_T('/'));
	int nFind = max(nFind1, nFind2);
	if(nFind != -1)
	{
		strPath = strPath.Left(nFind);
		if(PathFileExists(strPath) == FALSE)
		{
			SHCreateDirectoryEx(NULL, strPath, NULL);
		}
	}
#ifdef _UNICODE
    USES_CONVERSION;	
	if(img.Save(W2A(lpszFileName), dwType) == FALSE)
	{
		return FALSE;
	}
#else
	if(img.Save(lpszFileName, dwType) == FALSE)
	{
		return FALSE;
	}
#endif	
	img.Clear();
	return TRUE;
}

BOOL CSonicImage::Gray()
{
	if(m_Dib.IsValid() == FALSE)
	{
		return FALSE;
	}
	int nSrcSize = m_nWidth * m_nHeight * 4;
	CSSE::DoGray(m_Dib.GetBits(), nSrcSize);
	return TRUE;
}

HRGN CSonicImage::CreateRgn(DWORD dwColorKey /* = DEFAULT_COLOR_KEY */, int x /* = 0 */, int y /* = 0 */, RECT * pRtSrc /* = NULL */, BOOL bReverse /* = FALSE */)
{
	if(m_Dib.IsValid() == FALSE)
	{
		return FALSE;
	}

	int nBytePixel = 4;
	BYTE * pSrc = m_Dib.GetBits();

	CRect rtSrc(0, 0, m_nWidth, m_nHeight);
	if(pRtSrc)
	{
		rtSrc = *pRtSrc;
	}

	int nLeftx = -1;
	HRGN hAll = CreateRectRgn(x, y, x + rtSrc.Width(), y + rtSrc.Height());

	for(int i = rtSrc.top; i < rtSrc.bottom; i++)
	{
		for(int j = rtSrc.left; j < rtSrc.right; j++)
		{
			DWORD dwColor = *(DWORD *)(pSrc + (i * m_nWidth * nBytePixel) + j * nBytePixel);
			if(!bReverse)
			{
				if(EQUAL_24COLOR(dwColor, dwColorKey) && nLeftx < 0)
				{
					nLeftx = j;
				}
				if(nLeftx >= 0 && (!EQUAL_24COLOR(dwColor, dwColorKey) || j + 1 == rtSrc.right))
				{
					if(EQUAL_24COLOR(dwColor, dwColorKey) && j + 1 == rtSrc.right)j++;
					HRGN hTemp = CreateRectRgn(x + nLeftx - rtSrc.left, y + i - rtSrc.top, x + j - rtSrc.left, y + i + 1 - rtSrc.top);
					CombineRgn(hAll, hAll, hTemp, RGN_XOR);
					DeleteObject(hTemp);
					nLeftx = -1;
				}
			}
			else
			{
				if(!EQUAL_24COLOR(dwColor, dwColorKey) && nLeftx < 0)
				{
					nLeftx = j;
				}
				if(nLeftx >= 0 && (EQUAL_24COLOR(dwColor, dwColorKey) || j + 1 == rtSrc.right))
				{
					if(!EQUAL_24COLOR(dwColor, dwColorKey) && j + 1 == rtSrc.right)j++;
					HRGN hTemp = CreateRectRgn(x + nLeftx - rtSrc.left, y + i - rtSrc.top, x + j - rtSrc.left, y + i + 1 - rtSrc.top);
					CombineRgn(hAll, hAll, hTemp, RGN_XOR);
					DeleteObject(hTemp);
					nLeftx = -1;
				}
			}
		}
	}
	return hAll;
}

BOOL CSonicImage::IsAlphaChannelValid()
{
	return m_bAlphaChannel;
}

BOOL CSonicImage::EnableAlphaChannel(BOOL bModifyRgb /* = TRUE */)
{
	if(m_bAlphaChannel)
	{
		return FALSE;
	}
	if(m_Dib.IsValid() == FALSE)
	{
		return FALSE;
	}
	m_bAlphaChannel = TRUE;
	if(bModifyRgb)
	{
		int nSrc = m_nWidth * m_nHeight;
		DWORD * pSrc = (DWORD *)m_Dib.GetBits();
		for(int i = 0; i < nSrc; i++)
		{
			CSSE::AdjustAlpha(*pSrc);
			pSrc++;
		}
	}
	return TRUE;
}

DWORD CSonicImage::GetPixel(int x, int y)
{
	if(m_Dib.IsValid() == FALSE)
	{
		return 0;
	}
	if(y < 0 || y >= m_nHeight)
	{
		return 0;
	}
	if(x < 0 || x >= m_nWidth)
	{
		return 0;
	}
	return *(DWORD *)(m_Dib.GetBits() + (m_nHeight - y - 1) * m_nWidth * 4 + x * 4);
}

BOOL CSonicImage::SetPixel(int x, int y, DWORD dwColor)
{
	if(m_Dib.IsValid() == FALSE)
	{
		return 0;
	}
	if(IsAlphaChannelValid())
	{
		CSSE::AdjustAlpha(dwColor);
	}
	else
	{
		dwColor |= 0xff000000;
	}
	if(y < 0 || y >= m_nHeight)
	{
		return 0;
	}
	if(x < 0 || x >= m_nWidth)
	{
		return 0;
	}
	*(DWORD *)(m_Dib.GetBits() + (m_nHeight - y - 1) * m_nWidth * 4 + x * 4) = dwColor;
	return TRUE;
}

BYTE * CSonicImage::GetBits()
{
	return m_Dib.GetBits();
}

BOOL CSonicImage::Init()
{
	double radiant;
	for(int i = 0; i < 361; i++)
	{
		radiant = (i * PAI) / 180;
		double temp = sin(radiant) * 1024;
		Trigonometry[i][0] = ROUND(temp);
		temp = cos(radiant) * 1024;
		Trigonometry[i][1] = ROUND(temp);
	}
	return TRUE;
}

BOOL CSonicImage::SetBitsToDevice(HDC hdc, int x /* = 0 */, int y /* = 0 */)
{
	return SetDIBitsToDevice(hdc, x, y, m_nWidth, m_nHeight, 0, 0, 0, m_nHeight, m_Dib.GetBits(), m_Dib.GetBitmapInfo(), DIB_RGB_COLORS) != 0;
}

RECT CSonicImage::CalculateRectByDrawParam(int x, int y, const DRAW_PARAM * pDp, RECT * pSrc /* = NULL */)
{
	CRect rtSrc, rtDest;
	int cx = m_nWidth;
	int cy = m_nHeight;

	if(pDp && (pDp->dwMask & DP_SRC_CLIP))
	{
		rtSrc = pDp->rtSrc;
	}
	else
	{
		rtSrc.SetRect(0, 0, m_nWidth, m_nHeight);
	}
	cx = rtSrc.Width();
	cy = rtSrc.Height();
	if(pDp)
	{
		if(pDp->dwMask & DP_SCALE)
		{
			cx = (int)(rtSrc.Width() * pDp->fScaleX);
			cy = (int)(rtSrc.Height() * pDp->fScaleY);
		}
		if(pDp->dwMask & DP_DEST_LIMIT)
		{
			cx = pDp->cx;
			cy = pDp->cy;
		}
		if(pDp->dwMask & DP_TILE)
		{
			cx = pDp->nTileLength;
		}
		if(pDp->dwMask & DP_VER_TILE)
		{
			cy = pDp->nTileLength;
		}
	}
	rtDest.SetRect(x, y, x + cx, y + cy);
	if(pSrc)
	{
		*pSrc = rtSrc;
	}
	return rtDest;
}

BOOL CSonicImage::SetColorKey(DWORD dwColor)
{
	if(IsAlphaChannelValid())
	{
		return FALSE;
	}
	CSSE::SetColorKey(m_Dib.GetBits(), m_Dib.GetSize(), dwColor);
	EnableAlphaChannel(FALSE);
	return TRUE;
}

BOOL CSonicImage::Load(HDC hdc, int x, int y, int cx, int cy, BOOL bAlphaChannel /* = FALSE */)
{
	Clear();
	BITMAP bmp;
	GetObject((HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP), sizeof(bmp), &bmp);
	if(bmp.bmType != 0 || bmp.bmPlanes != 1)
	{
		return FALSE;
	}
	if(bmp.bmBitsPixel != 32)
	{
		return FALSE;
	}

	if(PrepareMemDC(cx, cy) == FALSE)
	{
		return FALSE;
	}
	BitBlt(m_Dib.GetSafeHdc(), 0, 0, cx, cy, hdc, x, y, SRCCOPY);
	if(bAlphaChannel)
	{
		EnableAlphaChannel(FALSE);
		CSSE::DoOr(0xff000000, m_Dib.GetBits(), m_Dib.GetSize());
	}
	return TRUE;
}

BOOL CSonicImage::Create(int cx, int cy, DWORD dwColor /* = 0 */, BOOL bWithAlpha /* = FALSE */)
{
	if(PrepareMemDC(cx, cy) == FALSE)
	{
		return FALSE;
	}
	if(bWithAlpha)
	{
		CSSE::AdjustAlpha(dwColor);
		EnableAlphaChannel(FALSE);
	}
	if(dwColor)
	{
		Flush(dwColor);
	}
	return TRUE;
}

BOOL CSonicImage::Flush(DWORD dwColor)
{
	if(m_Dib.IsValid() == FALSE)
	{
		return FALSE;
	}
	CSSE::MemSetDWord(m_Dib.GetBits(), dwColor, m_Dib.GetSize());
	return TRUE;
}

BOOL CSonicImage::SetHsl(int h /* = -1 */, int s /* = -1 */, int l /* = -1 */)
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}
	CSSE::SetHSL(m_Dib.GetBits(), m_Dib.GetSize(), h, s, l);
	return TRUE;
}

BOOL CSonicImage::MirrorX()
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}
	CSSE::MirrorX(m_Dib.GetBits(), m_nWidth, m_nHeight);
	return TRUE;
}

BOOL CSonicImage::MirrorY()
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}
	CSSE::MirrorY(m_Dib.GetBits(), m_nWidth, m_nHeight);
	return TRUE;
}

BOOL CSonicImage::Stretch(int cx, int cy)
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}
	if(cx == m_nWidth && cy == m_nHeight)
	{
		return TRUE;
	}
	CSonicImage * pImg = (CSonicImage *)g_UI.CreateImage();
	pImg->CloneFrom(this);
	PrepareMemDC(cx, cy);
	CSSE::Stretch(pImg->m_Dib.GetBits(), pImg->GetWidth(), pImg->GetHeight(), m_Dib.GetBits(), cx, cy);
	g_UI.DestroyObject(pImg);
	return TRUE;
}

BOOL CSonicImage::Extend(int cx /* = 0 */, int cy /* = 0 */)
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}
	cx = (cx == 0 ? m_nWidth : cx);
	cy = (cy == 0 ? m_nHeight : cy);
	CSonicImage * pImg = (CSonicImage *)g_UI.CreateImage();
	pImg->CloneFrom(this);

	PrepareMemDC(cx, cy);
	for(int i = 0; i < cy; i += pImg->GetHeight())
	{
		for(int j = 0; j < cx; j += pImg->GetWidth())
		{
			pImg->SetBitsToDevice(m_Dib.GetSafeHdc(), j, i);
		}
	}
	g_UI.DestroyObject(pImg);
	return TRUE;
}

HDC CSonicImage::GetDC()
{
	if(IsValid() == FALSE)
	{
		return NULL;
	}
	return m_Dib.GetSafeHdc();
}

BOOL CSonicImage::DestroyAlphaChannel()
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}
	CSSE::DoAnd(0xffffff, (char *)m_Dib.GetBits(), m_Dib.GetSize());
	return TRUE;
}

BOOL CSonicImage::SetAlphaChannel(BYTE bAlpha)
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}
	CSSE::DoOr((bAlpha << 24), (char *)m_Dib.GetBits(), m_Dib.GetSize());
	EnableAlphaChannel(FALSE);
	return TRUE;
}

BOOL CSonicImage::Blur(int nType /* = 0 */)
{
	if(IsValid() == FALSE)
	{
		return FALSE;
	}

	char * pTemp = new char[m_Dib.GetSize()];
	CSSE::MemCopy(pTemp, m_Dib.GetBits(), m_Dib.GetSize());
	int i, j;
	DWORD * pSrc = (DWORD *)m_Dib.GetBits();
	DWORD * pDest = (DWORD *)pTemp;
	for(i = 1; i < m_Dib.GetHeight() - 1; i++)
	{
		for(j = 1; j < m_Dib.GetWidth() - 1; j++)
		{
			DWORD dw1 = *(pDest + i * m_Dib.GetWidth() + j);
			DWORD dw2 = *(pDest + i * m_Dib.GetWidth() + j - 1);
			DWORD dw3 = *(pDest + i * m_Dib.GetWidth() + j + 1);
			DWORD dw4 = *(pDest + (i - 1) * m_Dib.GetWidth() + j);
			DWORD dw5 = *(pDest + (i + 1) * m_Dib.GetWidth() + j);
			DWORD dw6 = *(pDest + (i - 1) * m_Dib.GetWidth() + j - 1);
			DWORD dw7 = *(pDest + (i - 1) * m_Dib.GetWidth() + j + 1);
			DWORD dw8 = *(pDest + (i + 1) * m_Dib.GetWidth() + j - 1);
			DWORD dw9 = *(pDest + (i + 1) * m_Dib.GetWidth() + j + 1);
			char r, g, b;
			r = g = b = 0;
			switch (nType)
			{
			case 0:
				{
					// gauss blur
					r = ((GetRValue(dw1) << 2) +
						((GetRValue(dw2) +
						GetRValue(dw3) +
						GetRValue(dw4) +
						GetRValue(dw5)) << 1) + 
						GetRValue(dw6) +
						GetRValue(dw7) +
						GetRValue(dw8) +
						GetRValue(dw9)) >> 4;
					g = ((GetGValue(dw1) << 2) +
						((GetGValue(dw2) +
						GetGValue(dw3) +
						GetGValue(dw4) +
						GetGValue(dw5)) << 1) + 
						GetGValue(dw6) +
						GetGValue(dw7) +
						GetGValue(dw8) +
						GetGValue(dw9)) >> 4;
					b = ((GetBValue(dw1) << 2) +
						((GetBValue(dw2) +
						GetBValue(dw3) +
						GetBValue(dw4) +
						GetBValue(dw5)) << 1) + 
						GetBValue(dw6) +
						GetBValue(dw7) +
						GetBValue(dw8) +
						GetBValue(dw9)) >> 4;
				}
				break;
			case 1:
				{
					// even blur
					r = (GetRValue(dw1) +
						GetRValue(dw2) +
						GetRValue(dw3) +
						GetRValue(dw4) +
						GetRValue(dw5) + 
						GetRValue(dw6) +
						GetRValue(dw7) +
						GetRValue(dw8) +
						GetRValue(dw9)) / 9;
					g = (GetGValue(dw1) +
						GetGValue(dw2) +
						GetGValue(dw3) +
						GetGValue(dw4) +
						GetGValue(dw5) + 
						GetGValue(dw6) +
						GetGValue(dw7) +
						GetGValue(dw8) +
						GetGValue(dw9)) / 9;
					b = (GetBValue(dw1) +
						GetBValue(dw2) +
						GetBValue(dw3) +
						GetBValue(dw4) +
						GetBValue(dw5) + 
						GetBValue(dw6) +
						GetBValue(dw7) +
						GetBValue(dw8) +
						GetBValue(dw9)) / 9;
				}
				break;
			}
			
			*(pSrc + i * m_Dib.GetWidth() + j) = (0xff000000 | RGB(r, g, b));
		}
	}

	delete []pTemp;
	return TRUE;
}
// If handle_clipboard_request() fails, its caller sends VD_AGENT_CLIPBOARD message with type
// VD_AGENT_CLIPBOARD_NONE and no data, so the client will know the request failed.
bool VDAgent::handle_clipboard_request(VDAgentClipboardRequest* clipboard_request)
{
    VDAgentMessage* msg;
    uint32_t msg_size;
    UINT format;
    HANDLE clip_data;
    uint8_t* new_data = NULL;
    long new_size = 0;
    size_t len = 0;
    CxImage image;
    VDAgentClipboard* clipboard = NULL;

    if (_clipboard_owner != owner_guest) {
        vd_printf("Received clipboard request from client while clipboard is not owned by guest");
        return false;
    }
    if (!(format = get_clipboard_format(clipboard_request->type))) {
        vd_printf("Unsupported clipboard type %u", clipboard_request->type);
        return false;
    }
    // on encoding only, we use HBITMAP to keep the correct palette
    if (format == CF_DIB) {
        format = CF_BITMAP;
    }
    if (!IsClipboardFormatAvailable(format) || !OpenClipboard(_hwnd)) {
        return false;
    }
    if (!(clip_data = GetClipboardData(format))) {
        CloseClipboard();
        return false;
    }
    switch (clipboard_request->type) {
    case VD_AGENT_CLIPBOARD_UTF8_TEXT:
        if (!(new_data = (uint8_t*)GlobalLock(clip_data))) {
            break;
        }
        len = wcslen((LPCWSTR)new_data);
        new_size = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)new_data, (int)len, NULL, 0, NULL, NULL);
        break;
    case VD_AGENT_CLIPBOARD_IMAGE_PNG:
    case VD_AGENT_CLIPBOARD_IMAGE_BMP: {
        DWORD cximage_format = get_cximage_format(clipboard_request->type);
        HPALETTE pal = 0;

        ASSERT(cximage_format);
        if (IsClipboardFormatAvailable(CF_PALETTE)) {
            pal = (HPALETTE)GetClipboardData(CF_PALETTE);
        }
        if (!image.CreateFromHBITMAP((HBITMAP)clip_data, pal)) {
            vd_printf("Image create from handle failed");
            break;
        }
        if (!image.Encode(new_data, new_size, cximage_format)) {
            vd_printf("Image encode to type %u failed", clipboard_request->type);
            break;
        }
        vd_printf("Image encoded to %lu bytes", new_size);
        break;
    }
    }

    if (!new_size) {
        vd_printf("clipboard is empty");
        goto handle_clipboard_request_fail;
    }
    if ((_max_clipboard != -1) && (new_size > _max_clipboard)) {
        vd_printf("clipboard is too large (%ld > %d), discarding",
                  new_size, _max_clipboard);
        goto handle_clipboard_request_fail;
    }

    msg_size = sizeof(VDAgentMessage) + sizeof(VDAgentClipboard) + new_size;
    msg = (VDAgentMessage*)new uint8_t[msg_size];
    msg->protocol = VD_AGENT_PROTOCOL;
    msg->type = VD_AGENT_CLIPBOARD;
    msg->opaque = 0;
    msg->size = (uint32_t)(sizeof(VDAgentClipboard) + new_size);
    clipboard = (VDAgentClipboard*)msg->data;
    clipboard->type = clipboard_request->type;

    switch (clipboard_request->type) {
    case VD_AGENT_CLIPBOARD_UTF8_TEXT:
        WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)new_data, (int)len, (LPSTR)clipboard->data,
                            new_size, NULL, NULL);
        GlobalUnlock(clip_data);
        break;
    case VD_AGENT_CLIPBOARD_IMAGE_PNG:
    case VD_AGENT_CLIPBOARD_IMAGE_BMP:
        memcpy(clipboard->data, new_data, new_size);
        image.FreeMemory(new_data);
        break;
    }
    CloseClipboard();
    write_clipboard(msg, msg_size);
    delete[] (uint8_t *)msg;
    return true;

handle_clipboard_request_fail:
    if (clipboard_request->type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
       GlobalUnlock(clip_data);
    }
    CloseClipboard();
    return false;
}