bool WglBitmapBufferedContext::createOffScreenBitmap(const int colorBitCount, const int colorPlaneCount) { #if 0 // method #1 memBmp_ = CreateCompatibleBitmap(hDC_, drawRegion_.getWidth(), drawRegion_.getHeight()); //memBmp_ = CreateCompatibleBitmap(hDC_, (int)std::floor(viewingRegion_.getWidth() + 0.5), (int)std::floor(viewingRegion_.getHeight() + 0.5)); #else // method #2 const size_t bufSize = !isPaletteUsed_ ? sizeof(BITMAPINFO) : sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255; const boost::scoped_array<unsigned char> buf(new unsigned char [bufSize]); memset(buf.get(), 0, bufSize); BITMAPINFO &bmiDIB = *(BITMAPINFO *)buf.get(); // Following routine aligns given value to 4 bytes boundary. // The current implementation of DIB rendering in Windows 95/98/NT seems to be free from this alignment // but old version compatibility is needed. #if 1 const int width = ((drawRegion_.getWidth() + 3) / 4 * 4 > 0) ? drawRegion_.getWidth() : 4; const int height = (0 == drawRegion_.getHeight()) ? 1 : drawRegion_.getHeight(); #else const int viewingWidth = (int)std::floor(viewingRegion_.getWidth() + 0.5); const int viewingHeight = (int)std::floor(viewingRegion_.getHeight() + 0.5); const int width = ((viewingWidth + 3) / 4 * 4 > 0) ? viewingWidth : 4; const int height = (0 == viewingHeight) ? 1 : viewingHeight; #endif bmiDIB.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmiDIB.bmiHeader.biWidth = width; bmiDIB.bmiHeader.biHeight = height; bmiDIB.bmiHeader.biPlanes = colorPlaneCount; bmiDIB.bmiHeader.biBitCount = colorBitCount; if (!isPaletteUsed_) { bmiDIB.bmiHeader.biCompression = BI_RGB; bmiDIB.bmiHeader.biSizeImage = 0; // for BI_RGB // offscreen surface generated by the DIB section memBmp_ = CreateDIBSection(memDC_, &bmiDIB, DIB_RGB_COLORS, &dibBits_, NULL, 0); } else { // FIXME [check] >> bmiDIB.bmiHeader.biCompression = colorBitCount > 4 ? BI_RLE8 : BI_RLE4; bmiDIB.bmiHeader.biSizeImage = width * height * 3; // when using 256 color PALETTEENTRY paletteEntry[256]; GetPaletteEntries(shPalette_, 0, 256, paletteEntry); for (int i = 0; i < 256; ++i) { bmiDIB.bmiColors[i].rgbRed = paletteEntry[i].peRed; bmiDIB.bmiColors[i].rgbGreen = paletteEntry[i].peGreen; bmiDIB.bmiColors[i].rgbBlue = paletteEntry[i].peBlue; bmiDIB.bmiColors[i].rgbReserved = 0; } // offscreen surface generated by the DIB section memBmp_ = CreateDIBSection(memDC_, &bmiDIB, DIB_PAL_COLORS, &dibBits_, NULL, 0); } if (NULL == memBmp_ || NULL == dibBits_) return false; oldBmp_ = (HBITMAP)SelectObject(memDC_, memBmp_); #endif return true; }
/****************************************************************************** * OleTranslateColor [OLEAUT32.421] * * Convert an OLE_COLOR to a COLORREF. * * PARAMS * clr [I] Color to convert * hpal [I] Handle to a palette for the conversion * pColorRef [O] Destination for converted color, or NULL to test if the conversion is ok * * RETURNS * Success: S_OK. The conversion is ok, and pColorRef contains the converted color if non-NULL. * Failure: E_INVALIDARG, if any argument is invalid. * * FIXME * Document the conversion rules. */ HRESULT WINAPI OleTranslateColor( OLE_COLOR clr, HPALETTE hpal, COLORREF* pColorRef) { COLORREF colorref; BYTE b = HIBYTE(HIWORD(clr)); TRACE("(%08x, %p, %p)\n", clr, hpal, pColorRef); /* * In case pColorRef is NULL, provide our own to simplify the code. */ if (pColorRef == NULL) pColorRef = &colorref; switch (b) { case 0x00: { if (hpal != 0) *pColorRef = PALETTERGB(GetRValue(clr), GetGValue(clr), GetBValue(clr)); else *pColorRef = clr; break; } case 0x01: { if (hpal != 0) { PALETTEENTRY pe; /* * Validate the palette index. */ if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0) return E_INVALIDARG; } *pColorRef = clr; break; } case 0x02: *pColorRef = clr; break; case 0x80: { int index = LOBYTE(LOWORD(clr)); /* * Validate GetSysColor index. */ if ((index < COLOR_SCROLLBAR) || (index > COLOR_MENUBAR)) return E_INVALIDARG; *pColorRef = GetSysColor(index); break; } default: return E_INVALIDARG; } return S_OK; }
/****************************************************************************** * OleDuplicateData [OLE32.@] * * Duplicates clipboard data. * * PARAMS * hSrc [I] Handle of the source clipboard data. * cfFormat [I] The clipboard format of hSrc. * uiFlags [I] Flags to pass to GlobalAlloc. * * RETURNS * Success: handle to the duplicated data. * Failure: NULL. */ HANDLE WINAPI OleDuplicateData(HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags) { HANDLE hDst = NULL; TRACE("(%p,%x,%x)\n", hSrc, cfFormat, uiFlags); if (!uiFlags) uiFlags = GMEM_MOVEABLE; switch (cfFormat) { case CF_ENHMETAFILE: hDst = CopyEnhMetaFileW(hSrc, NULL); break; case CF_METAFILEPICT: hDst = CopyMetaFileW(hSrc, NULL); break; case CF_PALETTE: { LOGPALETTE * logpalette; UINT nEntries = GetPaletteEntries(hSrc, 0, 0, NULL); if (!nEntries) return NULL; logpalette = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(LOGPALETTE, palPalEntry[nEntries])); if (!logpalette) return NULL; if (!GetPaletteEntries(hSrc, 0, nEntries, logpalette->palPalEntry)) { HeapFree(GetProcessHeap(), 0, logpalette); return NULL; } logpalette->palVersion = 0x300; logpalette->palNumEntries = (WORD)nEntries; hDst = CreatePalette(logpalette); HeapFree(GetProcessHeap(), 0, logpalette); break; } case CF_BITMAP: { LONG size; BITMAP bm; if (!GetObjectW(hSrc, sizeof(bm), &bm)) return NULL; size = GetBitmapBits(hSrc, 0, NULL); if (!size) return NULL; bm.bmBits = HeapAlloc(GetProcessHeap(), 0, size); if (!bm.bmBits) return NULL; if (GetBitmapBits(hSrc, size, bm.bmBits)) hDst = CreateBitmapIndirect(&bm); HeapFree(GetProcessHeap(), 0, bm.bmBits); break; } default: { SIZE_T size = GlobalSize(hSrc); LPVOID pvSrc = NULL; LPVOID pvDst = NULL; /* allocate space for object */ if (!size) return NULL; hDst = GlobalAlloc(uiFlags, size); if (!hDst) return NULL; /* lock pointers */ pvSrc = GlobalLock(hSrc); if (!pvSrc) { GlobalFree(hDst); return NULL; } pvDst = GlobalLock(hDst); if (!pvDst) { GlobalUnlock(hSrc); GlobalFree(hDst); return NULL; } /* copy data */ memcpy(pvDst, pvSrc, size); /* cleanup */ GlobalUnlock(hDst); GlobalUnlock(hSrc); } } TRACE("returning %p\n", hDst); return hDst; }
static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFactory *iface, HBITMAP hbm, HPALETTE hpal, WICBitmapAlphaChannelOption option, IWICBitmap **bitmap) { BITMAP bm; HRESULT hr; WICPixelFormatGUID format; IWICBitmapLock *lock; UINT size, num_palette_entries = 0; PALETTEENTRY entry[256]; TRACE("(%p,%p,%p,%u,%p)\n", iface, hbm, hpal, option, bitmap); if (!bitmap) return E_INVALIDARG; if (GetObjectW(hbm, sizeof(bm), &bm) != sizeof(bm)) return WINCODEC_ERR_WIN32ERROR; if (hpal) { num_palette_entries = GetPaletteEntries(hpal, 0, 256, entry); if (!num_palette_entries) return WINCODEC_ERR_WIN32ERROR; } /* TODO: Figure out the correct format for 16, 32, 64 bpp */ switch(bm.bmBitsPixel) { case 1: format = GUID_WICPixelFormat1bppIndexed; break; case 4: format = GUID_WICPixelFormat4bppIndexed; break; case 8: format = GUID_WICPixelFormat8bppIndexed; break; case 16: if (!get_16bpp_format(hbm, &format)) return E_INVALIDARG; break; case 24: format = GUID_WICPixelFormat24bppBGR; break; case 32: switch (option) { case WICBitmapUseAlpha: format = GUID_WICPixelFormat32bppBGRA; break; case WICBitmapUsePremultipliedAlpha: format = GUID_WICPixelFormat32bppPBGRA; break; case WICBitmapIgnoreAlpha: format = GUID_WICPixelFormat32bppBGR; break; default: return E_INVALIDARG; } break; case 48: format = GUID_WICPixelFormat48bppRGB; break; default: FIXME("unsupported %d bpp\n", bm.bmBitsPixel); return E_INVALIDARG; } hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, &format, option, bitmap); if (hr != S_OK) return hr; hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); if (hr == S_OK) { BYTE *buffer; HDC hdc; char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; BITMAPINFO *bmi = (BITMAPINFO *)bmibuf; IWICBitmapLock_GetDataPointer(lock, &size, &buffer); hdc = CreateCompatibleDC(0); bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi->bmiHeader.biBitCount = 0; GetDIBits(hdc, hbm, 0, 0, NULL, bmi, DIB_RGB_COLORS); bmi->bmiHeader.biHeight = -bm.bmHeight; GetDIBits(hdc, hbm, 0, bm.bmHeight, buffer, bmi, DIB_RGB_COLORS); DeleteDC(hdc); IWICBitmapLock_Release(lock); if (num_palette_entries) { IWICPalette *palette; WICColor colors[256]; UINT i; hr = PaletteImpl_Create(&palette); if (hr == S_OK) { for (i = 0; i < num_palette_entries; i++) colors[i] = 0xff000000 | entry[i].peRed << 16 | entry[i].peGreen << 8 | entry[i].peBlue; hr = IWICPalette_InitializeCustom(palette, colors, num_palette_entries); if (hr == S_OK) hr = IWICBitmap_SetPalette(*bitmap, palette); IWICPalette_Release(palette); } } } if (hr != S_OK) { IWICBitmap_Release(*bitmap); *bitmap = NULL; } return hr; }
//+------------------------------------------------------------------------ // // Member: COffScreenContext::CreateDDSurface // // Synopsis: Create a DD surface with the specified dimensions and palette. // //------------------------------------------------------------------------- BOOL COffScreenContext::CreateDDSurface(long width, long height, HPALETTE hpal) { HRESULT hr = InitSurface(); if(FAILED(hr)) { return FALSE; } DDPIXELFORMAT* pPF = PixelFormat(_hdcWnd, _cBitsPixel); if(!pPF) { return FALSE; } DDSURFACEDESC ddsd; ddsd.dwSize = sizeof(ddsd); ddsd.ddpfPixelFormat = *pPF; ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_DATAEXCHANGE|DDSCAPS_OWNDC; if(_fUse3D) { ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; } ddsd.dwWidth = width; ddsd.dwHeight = height; hr = g_pDirectDraw->CreateSurface(&ddsd, &_pDDSurface, NULL); if(FAILED(hr)) { return FALSE; } // set color table if(_cBitsPixel <= 8) { IDirectDrawPalette* pDDPal; PALETTEENTRY* pPal; PALETTEENTRY pal256[256]; long cEntries; DWORD pcaps; if(_cBitsPixel == 8) { cEntries = GetPaletteEntries(hpal, 0, 256, pal256); pPal = pal256; pcaps = DDPCAPS_8BIT; } else if(_cBitsPixel == 4) { cEntries = 16; pPal = g_pal16; pcaps = DDPCAPS_4BIT; } else if(_cBitsPixel == 1) { cEntries = 2; pPal = g_pal2; pcaps = DDPCAPS_1BIT; } else { Assert(0 && "invalid cBitsPerPixel"); return FALSE; } // create and initialize a new DD palette hr = g_pDirectDraw->CreatePalette(pcaps|DDPCAPS_INITIALIZE, pPal, &pDDPal, NULL); if(SUCCEEDED(hr)) { // attach the DD palette to the DD surface hr = _pDDSurface->SetPalette(pDDPal); pDDPal->Release(); } if(FAILED(hr)) { return FALSE; } } hr = _pDDSurface->GetDC(&_hdcMem); return SUCCEEDED(hr); }
//+------------------------------------------------------------------------ // // Member: COffScreenContext::GetDDSurface // // Synopsis: Create a suitable DD surface or get one from the cache. // //------------------------------------------------------------------------- BOOL COffScreenContext::GetDDSurface(HPALETTE hpal) { HRESULT hr; LOCK_SECTION(g_csOscCache); if(!g_OscCache._fInUse) { ClearDDBCache(); // don't allow both DD & DDB in the cache if(g_OscCache._pDDSurface != NULL) { Assert(g_OscCache._fUseDD); if(_widthActual>g_OscCache._size.cx || _heightActual>g_OscCache._size.cy || _cBitsPixel!=g_OscCache._cBitsPixel || (_fUse3D&&!g_OscCache._fUse3D)) { ++g_OscCache._cMisses; ClearSurfaceCache(); } else { ++g_OscCache._cHits; g_OscCache._fInUse = TRUE; _pDDSurface = g_OscCache._pDDSurface; _pDDSurface->AddRef(); _hdcMem = g_OscCache._hdcMem; _widthActual = g_OscCache._size.cx; _heightActual = g_OscCache._size.cy; } } if(g_OscCache._pDDSurface == NULL) { // use max area allowed for the cache, so we get max reuse potential // favor width over height for those wide text runs // also adjust the max size in a growing fashion based on former allocations g_OscCache._size.cx = max(g_OscCache._size.cx, max(min(g_OscCache._areaTgt/_heightActual, g_OscCache._sizeTgt.cx), _widthActual)); g_OscCache._size.cy = max(g_OscCache._size.cy , max(g_OscCache._areaTgt/g_OscCache._size.cx, _heightActual)); if(!CreateDDSurface(g_OscCache._size.cx, g_OscCache._size.cy, hpal)) { return FALSE; } Trace0("surface cache created\n"); g_OscCache._fInUse = TRUE; g_OscCache._fUseDD = TRUE; g_OscCache._fUse3D = _fUse3D; g_OscCache._pDDSurface = _pDDSurface; g_OscCache._pDDSurface->AddRef(); // addref the global surface g_OscCache._cBitsPixel = _cBitsPixel; g_OscCache._hdcMem = _hdcMem; g_OscCache._hpal = hpal; _widthActual = g_OscCache._size.cx; _heightActual = g_OscCache._size.cy; } } else { Trace0("surface cache in use\n"); } if(_pDDSurface == NULL) { if(!CreateDDSurface(_widthActual, _heightActual, hpal)) { return FALSE; } } // reset the color table when using cache if(_cBitsPixel==8 && _pDDSurface==g_OscCache._pDDSurface && (hpal!=g_OscCache._hpal || hpal!=g_hpalHalftone)) { IDirectDrawPalette* pDDPal; PALETTEENTRY pal256[256]; long cEntries; cEntries = GetPaletteEntries(hpal, 0, 256, pal256); // get the DD palette and set entries hr = _pDDSurface->GetPalette(&pDDPal); if(SUCCEEDED(hr)) { hr = pDDPal->SetEntries(0, 0, cEntries, pal256); pDDPal->Release(); if(SUCCEEDED(hr)) { g_OscCache._hpal = hpal; } } } return TRUE; }
void tkSetFogRamp(int density, int startIndex) { HPALETTE CurrentPal; PALETTEENTRY *pPalEntry; UINT n, i, j, k, intensity, fogValues, colorValues; if ( NULL != (CurrentPal = CreateCIPalette(tkhdc)) ) { n = GetPaletteEntries( CurrentPal, 0, 0, NULL ); pPalEntry = AllocateMemory( n * sizeof(PALETTEENTRY) ); if ( NULL != pPalEntry) { fogValues = 1 << density; colorValues = 1 << startIndex; for (i = 0; i < colorValues; i++) { for (j = 0; j < fogValues; j++) { k = i * fogValues + j; intensity = i * fogValues + j * colorValues; //mf: not sure what they're trying to do here //intensity = (intensity << 8) | intensity; ??? // This is a workaround for a GDI palette "feature". If any of // the static colors are repeated in the palette, those colors // will map to the first occurance. So, for our case where there // are only two static colors (black and white), if a white // color appears anywhere in the palette other than in the last // entry, the static white will remap to the first white. This // destroys the nice one-to-one mapping we are trying to achieve. // // There are two ways to workaround this. The first is to // simply not allow a pure white anywhere but in the last entry. // Such requests are replaced with an attenuated white of // (0xFE, 0xFE, 0xFE). // // The other way is to mark these extra whites with PC_RESERVED // which will cause GDI to skip these entries when mapping colors. // This way the app gets the actual colors requested, but can // have side effects on other apps. // // Both solutions are included below. The PC_RESERVED solution is // the one currently enabled. It may have side effects, but taking // over the static colors as we are is a really big side effect that // should swamp out the effects of using PC_RESERVED. if (intensity > 0xFF) intensity = 0xFF; pPalEntry[k].peRed =pPalEntry[k].peGreen = pPalEntry[k].peBlue = (BYTE) intensity; pPalEntry[k].peFlags = 0; } } SetPaletteEntries(CurrentPal, 0, n, pPalEntry); FreeMemory( pPalEntry ); DelayPaletteRealization(); } } }
HDIB DibConvert (HDIB hdibSrc, int iBitCountDst) { HDIB hdibDst ; HPALETTE hPalette ; int i, x, y, cx, cy, iBitCountSrc, cColors ; PALETTEENTRY pe ; RGBQUAD rgb ; WORD wNumEntries ; cx = DibWidth (hdibSrc) ; cy = DibHeight (hdibSrc) ; iBitCountSrc = DibBitCount (hdibSrc) ; if (iBitCountSrc == iBitCountDst) return NULL ; // DIB with color table to DIB with larger color table: if ((iBitCountSrc < iBitCountDst) && (iBitCountDst <= 8)) { cColors = DibNumColors (hdibSrc) ; hdibDst = DibCreate (cx, cy, iBitCountDst, cColors) ; for (i = 0 ; i < cColors ; i++) { DibGetColor (hdibSrc, i, &rgb) ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibSetPixel (hdibDst, x, y, DibGetPixel (hdibSrc, x, y)) ; } } // Any DIB to DIB with no color table else if (iBitCountDst >= 16) { hdibDst = DibCreate (cx, cy, iBitCountDst, 0) ; for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixelColor (hdibDst, x, y, &rgb) ; } } // DIB with no color table to 8-bit DIB else if (iBitCountSrc >= 16 && iBitCountDst == 8) { hPalette = DibPalMedianCut (hdibSrc, 6) ; GetObject (hPalette, sizeof (WORD), &wNumEntries) ; hdibDst = DibCreate (cx, cy, 8, wNumEntries) ; for (i = 0 ; i < (int) wNumEntries ; i++) { GetPaletteEntries (hPalette, i, 1, &pe) ; rgb.rgbRed = pe.peRed ; rgb.rgbGreen = pe.peGreen ; rgb.rgbBlue = pe.peBlue ; rgb.rgbReserved = 0 ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixel (hdibDst, x, y, GetNearestPaletteIndex (hPalette, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ; } DeleteObject (hPalette) ; } // Any DIB to monochrome DIB else if (iBitCountDst == 1) { hdibDst = DibCreate (cx, cy, 1, 0) ; hPalette = DibPalUniformGrays (2) ; for (i = 0 ; i < 2 ; i++) { GetPaletteEntries (hPalette, i, 1, &pe) ; rgb.rgbRed = pe.peRed ; rgb.rgbGreen = pe.peGreen ; rgb.rgbBlue = pe.peBlue ; rgb.rgbReserved = 0 ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixel (hdibDst, x, y, GetNearestPaletteIndex (hPalette, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ; } DeleteObject (hPalette) ; } // All non-monochrome DIBs to 4-bit DIB else if (iBitCountSrc >= 8 && iBitCountDst == 4) { hdibDst = DibCreate (cx, cy, 4, 0) ; hPalette = DibPalVga () ; for (i = 0 ; i < 16 ; i++) { GetPaletteEntries (hPalette, i, 1, &pe) ; rgb.rgbRed = pe.peRed ; rgb.rgbGreen = pe.peGreen ; rgb.rgbBlue = pe.peBlue ; rgb.rgbReserved = 0 ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixel (hdibDst, x, y, GetNearestPaletteIndex (hPalette, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ; } DeleteObject (hPalette) ; } // Should not be necessary else hdibDst = NULL ; return hdibDst ; }
//************************************************************************ void SpeedCheck( LPOFFSCREEN lpOffScreen, PDIB pdib ) //************************************************************************ { #ifdef UNUSED RGBQUAD rgb1, rgb2; if (!lpOffScreen) return; HDC hdc; if ( !(hdc = GetDC(NULL)) ) return; WORD wNumEntries; GetObject( GetApp()->m_hPal, sizeof(WORD), (LPSTR)&wNumEntries ); PALETTEENTRY sEntries[256], pEntries[256]; GetPaletteEntries( GetApp()->m_hPal, 0, wNumEntries, pEntries ); GetSystemPaletteEntries( hdc, 0, 256, sEntries ); ReleaseDC( NULL, hdc ); if ( wNumEntries != 256 ) { Debug( "GetApp()->m_hPal only has %d entries\n", wNumEntries ); } // Compare the app's palette with the system palette int i; for ( i=0; i<256; i++ ) { if ( pEntries[i].peRed != sEntries[i].peRed || pEntries[i].peBlue != sEntries[i].peBlue || pEntries[i].peGreen != sEntries[i].peGreen ) // pEntries[i].peFlags != sEntries[i].peFlags ) { Debug( "GetApp()->m_hPal compare with syspal; entry %d (%d,%d,%d) (%d,%d,%d)\n", i, pEntries[i].peRed, pEntries[i].peGreen, pEntries[i].peBlue, sEntries[i].peRed, sEntries[i].peGreen, sEntries[i].peBlue ); // break; } } PDIB pdibr, pdibw; LPWORD lpIndices; // Compare the system palette with the WRITABLE offscreen if ( pdibw = lpOffScreen->GetWritableDIB() ) { RGBQUAD FAR *lprgbQuad = pdibw->GetColors(); for ( i=0; i<256; i++ ) { rgb1 = lprgbQuad[i]; if ( rgb1.rgbRed != sEntries[i].peRed || rgb1.rgbGreen != sEntries[i].peGreen || rgb1.rgbBlue != sEntries[i].peBlue ) { Debug( "OS writable compare with syspal; entry %d (%d,%d,%d) (%d,%d,%d)\n", i, rgb1.rgbRed, rgb1.rgbGreen, rgb1.rgbBlue, sEntries[i].peRed, sEntries[i].peGreen, sEntries[i].peBlue ); // break; } } } // Compare the READONLY offscreen with the WRITABLE offscreen if ( (pdibr = lpOffScreen->GetReadOnlyDIB()) && (pdibw = lpOffScreen->GetWritableDIB()) ) { RGBQUAD FAR *lprQuad = pdibr->GetColors(); RGBQUAD FAR *lpwQuad = pdibw->GetColors(); for ( i=0; i<256; i++ ) { rgb1 = lprQuad[i]; rgb2 = lpwQuad[i]; if ( rgb1.rgbRed != rgb2.rgbRed || rgb1.rgbGreen != rgb2.rgbGreen || rgb1.rgbBlue != rgb2.rgbBlue ) { Debug( "OS readonly compare with OS writable; entry %d (%d,%d,%d) (%d,%d,%d)\n", i, rgb1.rgbRed, rgb1.rgbGreen, rgb1.rgbBlue, rgb2.rgbRed, rgb2.rgbGreen, rgb2.rgbBlue ); // break; } } } // Compare the WRITABLE offscreen with a passed DIB if ( (pdibw = lpOffScreen->GetWritableDIB()) && pdib ) { RGBQUAD FAR *lpQuad = pdib->GetColors(); RGBQUAD FAR *lpwQuad = pdibw->GetColors(); for ( i=0; i<256; i++ ) { rgb1 = lpwQuad[i]; rgb2 = lpQuad[i]; if ( rgb1.rgbRed != rgb2.rgbRed || rgb1.rgbGreen != rgb2.rgbGreen || rgb1.rgbBlue != rgb2.rgbBlue ) { Debug( "OS writable compare with passed dib; entry %d (%d,%d,%d) (%d,%d,%d)\n", i, rgb1.rgbRed, rgb1.rgbGreen, rgb1.rgbBlue, rgb2.rgbRed, rgb2.rgbGreen, rgb2.rgbBlue ); // break; } } } // See if the WRITABLE offscreen is set to indices if ( pdibw = lpOffScreen->GetWritableDIB() ) { lpIndices = (LPWORD)pdibw->GetColors(); for ( i=0; i<256; i++ ) { if ( lpIndices[i] != (WORD)i ) { // Debug( "OS writable not indices; entry %d (%d)\n", i, lpIndices[i] ); // break; } } } // See if the READONLY offscreen is set to indices if ( pdibr = lpOffScreen->GetReadOnlyDIB() ) { lpIndices = (LPWORD)pdibr->GetColors(); for ( i=0; i<256; i++ ) { if ( lpIndices[i] != (WORD)i ) { // Debug( "OS readonly not indices; entry %d (%d)\n", i, lpIndices[i] ); // break; } } } #endif }
/**************************************************************************** * * FUNCTION: CopyColorTable * * PURPOSE: Copies the color table from one CF_DIB to another. * * PARAMS: LPBITMAPINFO lpTarget - pointer to target DIB * LPBITMAPINFO lpSource - pointer to source DIB * * RETURNS: BOOL - TRUE for success, FALSE for failure * * History: * July '95 - Created * \****************************************************************************/ BOOL CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource ) { // What we do depends on the target's color depth switch( lpTarget->bmiHeader.biBitCount ) { // 8bpp - need 256 entry color table case 8: if( lpSource->bmiHeader.biBitCount == 8 ) { // Source is 8bpp too, copy color table memcpy( lpTarget->bmiColors, lpSource->bmiColors, 256*sizeof(RGBQUAD) ); return TRUE; } else { // Source is != 8bpp, use halftone palette HPALETTE hPal; HDC hDC = GetDC( NULL ); PALETTEENTRY pe[256]; UINT i; hPal = CreateHalftonePalette( hDC ); ReleaseDC( NULL, hDC ); GetPaletteEntries( hPal, 0, 256, pe ); DeleteObject( hPal ); for(i=0;i<256;i++) { lpTarget->bmiColors[i].rgbRed = pe[i].peRed; lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; } return TRUE; } break; // end 8bpp // 4bpp - need 16 entry color table case 4: if( lpSource->bmiHeader.biBitCount == 4 ) { // Source is 4bpp too, copy color table memcpy( lpTarget->bmiColors, lpSource->bmiColors, 16*sizeof(RGBQUAD) ); return TRUE; } else { // Source is != 4bpp, use system palette HPALETTE hPal; PALETTEENTRY pe[256]; UINT i; hPal = GetStockObject( DEFAULT_PALETTE ); GetPaletteEntries( hPal, 0, 16, pe ); for(i=0;i<16;i++) { lpTarget->bmiColors[i].rgbRed = pe[i].peRed; lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; } return TRUE; } break; // end 4bpp // 1bpp - need 2 entry mono color table case 1: lpTarget->bmiColors[0].rgbRed = 0; lpTarget->bmiColors[0].rgbGreen = 0; lpTarget->bmiColors[0].rgbBlue = 0; lpTarget->bmiColors[0].rgbReserved = 0; lpTarget->bmiColors[1].rgbRed = 255; lpTarget->bmiColors[1].rgbGreen = 255; lpTarget->bmiColors[1].rgbBlue = 255; lpTarget->bmiColors[1].rgbReserved = 0; break; // end 1bpp // no color table for the > 8bpp modes case 32: case 24: case 16: default: return TRUE; break; } return TRUE; }
/* * clipboard_data_to_bytes - データをバイト列に変換 */ BYTE *clipboard_data_to_bytes(const DATA_INFO *di, DWORD *ret_size) { BYTE *ret = NULL; BYTE *tmp; DWORD i; DWORD size = 0; if (di->data == NULL) { return NULL; } switch (di->format) { case CF_PALETTE: // パレット i = 0; GetObject(di->data, sizeof(WORD), &i); size = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * i); if ((ret = mem_calloc(size)) == NULL) { break; } ((LOGPALETTE *)ret)->palVersion = 0x300; ((LOGPALETTE *)ret)->palNumEntries = (WORD)i; GetPaletteEntries(di->data, 0, i, ((LOGPALETTE *)ret)->palPalEntry); break; case CF_DSPBITMAP: case CF_BITMAP: // ビットマップ if ((ret = bitmap_to_dib(di->data, &size)) == NULL) { break; } break; case CF_OWNERDISPLAY: break; case CF_DSPMETAFILEPICT: case CF_METAFILEPICT: // メタファイル if ((tmp = GlobalLock(di->data)) == NULL) { break; } size = GetMetaFileBitsEx(((METAFILEPICT *)tmp)->hMF, 0, NULL); if ((ret = mem_alloc(size + sizeof(METAFILEPICT))) == NULL) { GlobalUnlock(di->data); break; } CopyMemory(ret, tmp, sizeof(METAFILEPICT)); if (GetMetaFileBitsEx(((METAFILEPICT *)tmp)->hMF, size, ret + sizeof(METAFILEPICT)) == 0) { mem_free(&ret); GlobalUnlock(di->data); break; } size += sizeof(METAFILEPICT); GlobalUnlock(di->data); break; case CF_DSPENHMETAFILE: case CF_ENHMETAFILE: // 拡張メタファイル size = GetEnhMetaFileBits(di->data, 0, NULL); if ((ret = mem_alloc(size)) == NULL) { break; } if (GetEnhMetaFileBits(di->data, size, ret) == 0) { mem_free(&ret); break; } break; default: // その他 if ((tmp = GlobalLock(di->data)) == NULL) { break; } size = di->size; if ((ret = mem_alloc(size)) == NULL) { GlobalUnlock(di->data); break; } CopyMemory(ret, tmp, size); GlobalUnlock(di->data); break; } if (ret_size != NULL) { *ret_size = size; } return ret; }
/* * clipboard_copy_data - クリップボードデータのコピーを作成 */ HANDLE clipboard_copy_data(const UINT format, const HANDLE data, DWORD *ret_size) { HANDLE ret = NULL; BYTE *from_mem, *to_mem; LOGPALETTE *lpal; WORD pcnt; if (data == NULL) { return NULL; } switch (format) { case CF_PALETTE: // パレット pcnt = 0; if (GetObject(data, sizeof(WORD), &pcnt) == 0) { return NULL; } if ((lpal = mem_calloc(sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * pcnt))) == NULL) { return NULL; } lpal->palVersion = 0x300; lpal->palNumEntries = pcnt; if (GetPaletteEntries(data, 0, pcnt, lpal->palPalEntry) == 0) { mem_free(&lpal); return NULL; } ret = CreatePalette(lpal); *ret_size = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * pcnt); mem_free(&lpal); break; case CF_DSPBITMAP: case CF_BITMAP: // ビットマップ if ((to_mem = bitmap_to_dib(data, ret_size)) == NULL) { return NULL; } ret = dib_to_bitmap(to_mem); mem_free(&to_mem); break; case CF_OWNERDISPLAY: *ret_size = 0; break; case CF_DSPMETAFILEPICT: case CF_METAFILEPICT: // コピー元ロック if ((from_mem = GlobalLock(data)) == NULL) { return NULL; } // メタファイル if ((ret = GlobalAlloc(GHND, sizeof(METAFILEPICT))) == NULL) { GlobalUnlock(data); return NULL; } // コピー先ロック if ((to_mem = GlobalLock(ret)) == NULL) { GlobalFree(ret); GlobalUnlock(data); return NULL; } CopyMemory(to_mem, from_mem, sizeof(METAFILEPICT)); if ((((METAFILEPICT *)to_mem)->hMF = CopyMetaFile(((METAFILEPICT *)from_mem)->hMF, NULL)) != NULL) { *ret_size = sizeof(METAFILEPICT) + GetMetaFileBitsEx(((METAFILEPICT *)to_mem)->hMF, 0, NULL); } // ロック解除 GlobalUnlock(ret); GlobalUnlock(data); break; case CF_DSPENHMETAFILE: case CF_ENHMETAFILE: // 拡張メタファイル if ((ret = CopyEnhMetaFile(data, NULL)) != NULL) { *ret_size = GetEnhMetaFileBits(ret, 0, NULL); } break; default: // その他 // メモリチェック if (IsBadReadPtr(data, 1) == TRUE) { return NULL; } // サイズ取得 if ((*ret_size = GlobalSize(data)) == 0) { return NULL; } // コピー元ロック if ((from_mem = GlobalLock(data)) == NULL) { return NULL; } // コピー先確保 if ((ret = GlobalAlloc(GHND, *ret_size)) == NULL) { GlobalUnlock(data); return NULL; } // コピー先ロック if ((to_mem = GlobalLock(ret)) == NULL) { GlobalFree(ret); GlobalUnlock(data); return NULL; } // コピー CopyMemory(to_mem, from_mem, *ret_size); // ロック解除 GlobalUnlock(ret); GlobalUnlock(data); break; } return ret; }
//--------------------------------------------------------------------------- void __fastcall TDeePNG::SaveToStream(Classes::TStream * Stream) { // SaveToStream method // warning: this method would change the pixelformat to pf24bit // if the pixelformat is pfDevice, pf15bit, pf16bit, or pfCustom. png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep row_buffer = NULL; try { // create png_struct png_ptr = png_create_write_struct_2 (PNG_LIBPNG_VER_STRING, (png_voidp)this, DeePNG_error, DeePNG_warning, (png_voidp)this, DeePNG_malloc, DeePNG_free); // create png_info info_ptr = png_create_info_struct(png_ptr); // set write function png_set_write_fn(png_ptr, (png_voidp)Stream, DeePNG_write_data, DeePNG_flush); // set IHDR if(PixelFormat == pfDevice || PixelFormat == pf15bit || PixelFormat == pf16bit || PixelFormat == pfCustom) PixelFormat = pf24bit; bool grayscale = IsGrayscaleBitmap(this); int colordepth = GetBitmapColorDepth(this); int w = Width; int h = Height; int color_type; if(grayscale) color_type = PNG_COLOR_TYPE_GRAY; else if(colordepth <= 8) color_type = PNG_COLOR_TYPE_PALETTE; else if(colordepth == 32) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, w, h, colordepth < 8 ? colordepth : 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // set oFFs if(ofs_set) png_set_oFFs(png_ptr, info_ptr, ofs_x, ofs_y, ofs_unit); // set palette if(color_type == PNG_COLOR_TYPE_PALETTE) { png_color *palette = (png_colorp)png_malloc(png_ptr, 256 * sizeof(png_color)); PALETTEENTRY palentry[256]; int num_palette = GetPaletteEntries(Palette, 0, (1<<colordepth), palentry); for(int i = 0; i < num_palette; i++) { palette[i].red = palentry[i].peRed; palette[i].green = palentry[i].peGreen; palette[i].blue = palentry[i].peBlue; } png_set_PLTE(png_ptr, info_ptr, palette, num_palette); } // write info png_write_info(png_ptr, info_ptr); // write vpAg private chunk if(vpag_set) { png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; unsigned char vpag_chunk_data[9]; #define PNG_write_be32(p, a) (\ ((unsigned char *)(p))[0] = (unsigned char)(((a) >>24) & 0xff), \ ((unsigned char *)(p))[1] = (unsigned char)(((a) >>16) & 0xff), \ ((unsigned char *)(p))[2] = (unsigned char)(((a) >> 8) & 0xff), \ ((unsigned char *)(p))[3] = (unsigned char)(((a) ) & 0xff) ) PNG_write_be32(vpag_chunk_data, vpag_w); PNG_write_be32(vpag_chunk_data + 4, vpag_h); vpag_chunk_data[8] = (unsigned char)vpag_unit; png_write_chunk(png_ptr, png_vpAg, vpag_chunk_data, 9); } /* // change RGB order if(color_type = PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); // ???? why this does not work ? */ // write image if(color_type == PNG_COLOR_TYPE_RGB) { row_buffer = (png_bytep)png_malloc(png_ptr, 3 * w + 6); try { png_bytep row_pointer = row_buffer; for(int i = 0; i < h; i++) { png_bytep in = (png_bytep)ScanLine[i]; png_bytep out = row_buffer; for(int x = 0; x < w; x++) { out[2] = in[0]; out[1] = in[1]; out[0] = in[2]; out += 3; in += 3; } png_write_row(png_ptr, row_pointer); } } catch(...) { png_free(png_ptr, row_buffer); throw; } png_free(png_ptr, row_buffer); } else if(color_type == PNG_COLOR_TYPE_RGB_ALPHA) { row_buffer = (png_bytep)png_malloc(png_ptr, 4 * w + 6); try { png_bytep row_pointer = row_buffer; for(int i = 0; i < h; i++) { png_bytep in = (png_bytep)ScanLine[i]; png_bytep out = row_buffer; for(int x = 0; x < w; x++) { out[2] = in[0]; out[1] = in[1]; out[0] = in[2]; out[3] = in[3]; out += 4; in += 4; } png_write_row(png_ptr, row_pointer); } } catch(...) { png_free(png_ptr, row_buffer); throw; } png_free(png_ptr, row_buffer); } else { for(int i = 0; i < h; i++) { png_bytep row_pointer = (png_bytep)ScanLine[i]; png_write_row(png_ptr, row_pointer); } } // finish writing png_write_end(png_ptr, info_ptr); } catch(...) { png_destroy_write_struct(&png_ptr, &info_ptr); throw; } png_destroy_write_struct(&png_ptr, &info_ptr); }