📄 bitmap.cpp
字号:
// Bitmap.cpp : Implementation of CBitmap
#include "stdafx.h"
#include "Picture.h"
#include "Pixels.h"
#include "Bitmap.h"
#include "Pixel.h"
// Standard windows 16 colors palette:
const RGBQUAD colorTable[16] =
{
{ 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x80, 0x00 },
{ 0x00, 0x80, 0x00, 0x00 },
{ 0x00, 0x80, 0x80, 0x00 },
{ 0x80, 0x00, 0x00, 0x00 },
{ 0x80, 0x00, 0x80, 0x00 },
{ 0x80, 0x80, 0x00, 0x00 },
{ 0x80, 0x80, 0x80, 0x00 },
{ 0xC0, 0xC0, 0xC0, 0x00 },
{ 0x00, 0x00, 0xFF, 0x00 },
{ 0x00, 0xFF, 0x00, 0x00 },
{ 0x00, 0xFF, 0xFF, 0x00 },
{ 0xFF, 0x00, 0x00, 0x00 },
{ 0xFF, 0x00, 0xFF, 0x00 },
{ 0xFF, 0xFF, 0x00, 0x00 },
{ 0xFF, 0xFF, 0xFF, 0x00 },
};
///////////////////////////////////////////////////////////////////
// CBitmap
STDMETHODIMP CBitmap::get_AutoSize(VARIANT_BOOL *pVal)
{
*pVal = m_bAutoSize;
return S_OK;
}
STDMETHODIMP CBitmap::put_AutoSize(VARIANT_BOOL newVal)
{
m_bAutoSize = newVal;
return S_OK;
}
STDMETHODIMP CBitmap::get_Width(long *pVal)
{
*pVal = m_width;
return S_OK;
}
STDMETHODIMP CBitmap::put_Width(long newVal)
{
return UpdateSize(newVal, m_height);
}
STDMETHODIMP CBitmap::get_Height(long *pVal)
{
*pVal = m_height;
return S_OK;
}
STDMETHODIMP CBitmap::put_Height(long newVal)
{
return UpdateSize(m_width, newVal);
}
HRESULT CBitmap::UpdateSize(long lWidth, long lHeight)
{
// Set the m_bitmap pointer to a new size
DWORD dwNewSize; // New array size
// Keep a pointer on the old bitmap
LPBYTE pOldBitmap = m_bitmap;
// Calculate the new bitmap size
dwNewSize = lHeight * CBROW(lWidth);
// Allocate memory for the new bitmap
if (NULL == (m_bitmap = (LPBYTE)CoTaskMemAlloc(dwNewSize)))
{
m_bitmap = pOldBitmap;
return E_OUTOFMEMORY;
}
// Set the bitmap with a White background
memset(m_bitmap, (White | (White << 4)), dwNewSize);
// Update new width and length members
long oldWidth = m_width;
long oldHeight = m_height;
m_width = lWidth;
m_height = lHeight;
// Calculate the number of bytes to copy for each line
DWORD cbToCopy;
if (oldWidth < m_width)
cbToCopy = CBROW(oldWidth);
else
cbToCopy = CBROW(m_width);
// Copy the part of the old bitmap part that could fit in the
// new one by copying it line by line
LPBYTE lpOldRow = pOldBitmap, lpNewRow = m_bitmap;
if (pOldBitmap != NULL)
{
for (int iRow = 0; iRow < oldHeight; iRow++)
{
// Did height growed or shrinked ?
if (oldHeight < m_height)
{
if (iRow >= oldHeight) break;
} else if (iRow >= m_height) break;
// Copy the bitmap row from the old to the new bitmap
CopyMemory(lpNewRow, lpOldRow, cbToCopy);
// Go to next row
lpOldRow += CBROW(oldWidth);
lpNewRow += CBROW(lWidth);
}
// Free the old bitmap memory data
CoTaskMemFree(pOldBitmap);
}
return (m_bitmap ? S_OK : E_OUTOFMEMORY);
}
STDMETHODIMP CBitmap::SetPoints(VARIANT vPoints)
{
// Read a set of points defined in vPoints to apply them to
// the current picture
if (!(vPoints.vt & VT_VARIANT) ||
!(vPoints.vt & VT_BYREF)) return E_INVALIDARG;
// Get the low and upper bound of the array
HRESULT hr = S_OK;
SAFEARRAY* pArray = *vPoints.pvarVal->pparray;
LONG lBound, uBound;
if (FAILED(SafeArrayGetLBound(pArray, 1, &lBound)) ||
FAILED(SafeArrayGetUBound(pArray, 1, &uBound)))
return E_INVALIDARG;
// And set the point for each pixel of the array
for (long iPixel = lBound; iPixel < uBound; iPixel++)
{
// Get the Pixel object
VARIANT vPixel;
SafeArrayGetElement(pArray, &iPixel, &vPixel);
// Set the point by forwarding the object to SetPoint
if (vPixel.vt == VT_DISPATCH || vPixel.vt == VT_UNKNOWN)
{
CComQIPtr<IPixel> pPixel = vPixel.pdispVal;
if (pPixel.p && FAILED(hr = SetPoint(pPixel))) break;
}
}
return hr;
}
STDMETHODIMP CBitmap::SetPoint(IPixel *pPixel)
{
HRESULT hr = S_OK;
long col, row;
// Get pixel data
pPixel->get_Row(&row);
pPixel->get_Column(&col);
// Use put_Pixel to set it
return m_pPixels->put_Pixel(col, row, pPixel);
}
STDMETHODIMP CBitmap::SaveToStream(LPSTREAM pStm)
{
// Get the size of the bitmap buffer (required for the bfSize
// member of the bitmap file header
CComPtr<IMalloc> pMalloc;
CoGetMalloc(1, &pMalloc);
DWORD cbBitmapData = pMalloc->GetSize(m_bitmap);
// Set the bitmap fileheader to the stream
BITMAPFILEHEADER bfh;
bfh.bfType = *((WORD*)"BM");
bfh.bfSize = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
sizeof(colorTable) +
cbBitmapData;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
sizeof(colorTable);
// Set the 16 colors bitmap info to the stream
BITMAPINFOHEADER bih;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = m_width;
bih.biHeight = m_height;
bih.biPlanes = 1;
bih.biBitCount = 4; // 16 colors bitmap (4 bits)
bih.biCompression = 0;
bih.biSizeImage = cbBitmapData;
bih.biXPelsPerMeter = 0xE0C4;
bih.biYPelsPerMeter = 0xE0C4;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
// Write now all the information into the stream
HRESULT hr;
hr = pStm->Write(&bfh, sizeof(BITMAPFILEHEADER), NULL);
hr = pStm->Write(&bih, sizeof(BITMAPINFOHEADER), NULL);
hr = pStm->Write(colorTable, sizeof(colorTable), NULL);
hr = pStm->Write(m_bitmap, cbBitmapData, NULL);
return hr;
}
STDMETHODIMP CBitmap::SaveToIIS4Response(VARIANT vResponse)
{
CComVariant vDispResponse;
if (SUCCEEDED(vDispResponse.ChangeType(VT_DISPATCH, &vResponse)))
{
// Get the pointer to IResponse
CComQIPtr<IResponse> pResponse = vDispResponse.pdispVal;
if (pResponse.p == NULL) return E_INVALIDARG;
// Get the data to write to the ASP Response Object
HRESULT hr;
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);
CComPtr<IStream> pStm;
if (FAILED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStm)) ||
FAILED(hr = SaveToStream(pStm))) return hr;
// Set the data to in the SAFEARRAY format
UINT cElements = GlobalSize(hGlobal);
LPBYTE lpData = (LPBYTE)GlobalLock(hGlobal);
// Create a single-dimension array (i.e. a vector)
SAFEARRAY* pArray = SafeArrayCreateVector(VT_UI1, 0, cElements);
for (UINT iElement = 0; iElement < cElements; iElement++)
{
// Set each bytes of data in the safe array
long idx = iElement;
SafeArrayPutElement(pArray, &idx, ((LPBYTE)lpData) + iElement);
}
GlobalUnlock(hGlobal);
// Write the data to the HTTP answer
CComVariant vBytes;
vBytes.vt = VT_ARRAY | VT_UI1;
vBytes.parray = pArray;
return pResponse->BinaryWrite(vBytes);
}
else
return E_INVALIDARG;
}
STDMETHODIMP CBitmap::SaveToFile(VARIANT vbstrFileName,
VARIANT vhWndParentWindow)
{
USES_CONVERSION;
// Verify the handle to the window parent is present and valid
HWND hWndParent = NULL;
if (! (vhWndParentWindow.vt == VT_EMPTY ||
(vhWndParentWindow.vt == VT_ERROR &&
vhWndParentWindow.scode == DISP_E_PARAMNOTFOUND)) )
{
// Convert the Variant to VT_I4
CComVariant vParent = vhWndParentWindow;
if (FAILED(vParent.ChangeType(VT_I4)))
return AtlReportError(CLSID_Bitmap, IDS_BAD_HWND,
IID_IBitmap, 0, _Module.GetModuleInstance());
}
// Should we display a dialog-box asking for the filename
_TCHAR szFileName[MAX_PATH] = { 0 };
if (vbstrFileName.vt == VT_EMPTY ||
(vbstrFileName.vt == VT_ERROR &&
vbstrFileName.scode == DISP_E_PARAMNOTFOUND))
{
// Use GetSaveFileName to show the dialog-box
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWndParent;
ofn.hInstance = _Module.GetModuleInstance();
ofn.lpstrFilter = _T("Bitmap files\0*.BMP\0");
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFile = szFileName;
ofn.lpstrDefExt = _T(".BMP");
if (!GetSaveFileName(&ofn))
return S_OK;
}
else
{
// Assert it is a BSTR
if (vbstrFileName.vt != VT_BSTR)
return AtlReportError(CLSID_Bitmap, IDS_BAD_FILENAME,
IID_IBitmap, 0, _Module.GetModuleInstance());
// Copy the filename passed in parameters
lstrcpyn(szFileName,
W2T(vbstrFileName.bstrVal),
MAX_PATH - 1);
}
// Create a stream on a HGLOBAL and pass it to the save function
HRESULT hr;
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);
CComPtr<IStream> pStm;
if (FAILED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStm)) ||
FAILED(hr = SaveToStream(pStm))) return hr;
// Write now the stream to the specified file
LPBYTE lpMem = (LPBYTE)GlobalLock(hGlobal);
HANDLE hFile = CreateFile(szFileName, GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
DWORD cbWritten;
if (!WriteFile(hFile, lpMem, GlobalSize(hGlobal), &cbWritten, NULL))
{
return AtlReportError(CLSID_Bitmap, IDS_ERROR_SAVING,
IID_IBitmap, 0, _Module.GetModuleInstance());
} else CloseHandle(hFile);
return hr;
}
STDMETHODIMP CBitmap::get_Pixels(IPixels **pVal)
{
// Send our pixels object pointer
return m_pPixels->QueryInterface(pVal);
}
HRESULT CBitmap::TestCoordinates(long x, long y)
{
// Test if coordinates are valid or not
if (x >= m_width || y >= m_height)
return AtlReportError(CLSID_Bitmap, IDS_WRONG_COORDINATES,
IID_IBitmap, 0, _Module.GetModuleInstance());
else
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -