⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitmap.cpp

📁 Vc.Net入门与提高源码
💻 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 + -