📄 olepicture.c
字号:
bmi->bmiColors[1].rgbBlue = 255;
bmi->bmiHeader.biBitCount = 1;
bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
bmi->bmiHeader.biClrUsed = 2;
for (i = 0; i < gif->SHeight; i++) {
unsigned char * colorPointer = bytes + padding * i;
unsigned char * monoPointer = bytes + monopadding * i;
for (j = 0; j < gif->SWidth; j++) {
unsigned char pixel = colorPointer[j];
if ((j & 7) == 0) monoPointer[j >> 3] = 0;
if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
}
}
hdcref = GetDC(0);
hTempMask = CreateDIBitmap(
hdcref,
&bmi->bmiHeader,
CBM_INIT,
bytes,
bmi,
DIB_RGB_COLORS
);
DeleteDC(hdcref);
bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
hOldbitmap = SelectObject(hdc, hTempMask);
hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
SetBkColor(hdc, RGB(255, 255, 255));
BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
/* We no longer need the original bitmap, so we apply the first
transformation with the mask to speed up the rendering */
SelectObject(hdc, This->hbmXor);
SetBkColor(hdc, RGB(0,0,0));
SetTextColor(hdc, RGB(255,255,255));
BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
hdcMask, 0, 0, SRCAND);
SelectObject(hdc, hOldbitmap);
SelectObject(hdcMask, hOldbitmapmask);
DeleteDC(hdcMask);
DeleteDC(hdc);
DeleteObject(hTempMask);
}
DeleteDC(hdcref);
This->desc.picType = PICTYPE_BITMAP;
OLEPictureImpl_SetBitmap(This);
pDGifCloseFile(gif);
HeapFree(GetProcessHeap(),0,bytes);
return S_OK;
#else
FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
return E_FAIL;
#endif
}
static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
{
#ifdef HAVE_JPEGLIB_H
struct jpeg_decompress_struct jd;
struct jpeg_error_mgr jerr;
int ret;
JDIMENSION x;
JSAMPROW samprow,oldsamprow;
BITMAPINFOHEADER bmi;
LPBYTE bits;
HDC hdcref;
struct jpeg_source_mgr xjsm;
LPBYTE oldbits;
unsigned int i;
if(!libjpeg_handle) {
if(!load_libjpeg()) {
FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
return E_FAIL;
}
}
/* This is basically so we can use in-memory data for jpeg decompression.
* We need to have all the functions.
*/
xjsm.next_input_byte = xbuf;
xjsm.bytes_in_buffer = xread;
xjsm.init_source = _jpeg_init_source;
xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
xjsm.skip_input_data = _jpeg_skip_input_data;
xjsm.resync_to_restart = _jpeg_resync_to_restart;
xjsm.term_source = _jpeg_term_source;
jd.err = pjpeg_std_error(&jerr);
/* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
* jpeg_create_decompress(&jd); */
pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
jd.src = &xjsm;
ret=pjpeg_read_header(&jd,TRUE);
jd.out_color_space = JCS_RGB;
pjpeg_start_decompress(&jd);
if (ret != JPEG_HEADER_OK) {
ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
HeapFree(GetProcessHeap(),0,xbuf);
return E_FAIL;
}
bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
(jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
oldbits = bits;
oldsamprow = samprow;
while ( jd.output_scanline<jd.output_height ) {
x = pjpeg_read_scanlines(&jd,&samprow,1);
if (x != 1) {
FIXME("failed to read current scanline?\n");
break;
}
/* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
*(bits++) = *(samprow+2);
*(bits++) = *(samprow+1);
*(bits++) = *(samprow);
}
bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
samprow = oldsamprow;
}
bits = oldbits;
bmi.biSize = sizeof(bmi);
bmi.biWidth = jd.output_width;
bmi.biHeight = -jd.output_height;
bmi.biPlanes = 1;
bmi.biBitCount = jd.output_components<<3;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
bmi.biXPelsPerMeter = 0;
bmi.biYPelsPerMeter = 0;
bmi.biClrUsed = 0;
bmi.biClrImportant = 0;
HeapFree(GetProcessHeap(),0,samprow);
pjpeg_finish_decompress(&jd);
pjpeg_destroy_decompress(&jd);
hdcref = GetDC(0);
This->desc.u.bmp.hbitmap=CreateDIBitmap(
hdcref,
&bmi,
CBM_INIT,
bits,
(BITMAPINFO*)&bmi,
DIB_RGB_COLORS
);
DeleteDC(hdcref);
This->desc.picType = PICTYPE_BITMAP;
OLEPictureImpl_SetBitmap(This);
HeapFree(GetProcessHeap(),0,bits);
return S_OK;
#else
ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
return E_FAIL;
#endif
}
static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
{
BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
HDC hdcref;
/* Does not matter whether this is a coreheader or not, we only use
* components which are in both
*/
hdcref = GetDC(0);
This->desc.u.bmp.hbitmap = CreateDIBitmap(
hdcref,
&(bi->bmiHeader),
CBM_INIT,
xbuf+bfh->bfOffBits,
bi,
DIB_RGB_COLORS
);
DeleteDC(hdcref);
This->desc.picType = PICTYPE_BITMAP;
OLEPictureImpl_SetBitmap(This);
return S_OK;
}
static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
{
HICON hicon;
CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
HDC hdcRef;
int i;
/*
FIXME("icon.idReserved=%d\n",cifd->idReserved);
FIXME("icon.idType=%d\n",cifd->idType);
FIXME("icon.idCount=%d\n",cifd->idCount);
for (i=0;i<cifd->idCount;i++) {
FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
}
*/
i=0;
/* If we have more than one icon, try to find the best.
* this currently means '32 pixel wide'.
*/
if (cifd->idCount!=1) {
for (i=0;i<cifd->idCount;i++) {
if (cifd->idEntries[i].bWidth == 32)
break;
}
if (i==cifd->idCount) i=0;
}
hicon = CreateIconFromResourceEx(
xbuf+cifd->idEntries[i].dwDIBOffset,
cifd->idEntries[i].dwDIBSize,
TRUE, /* is icon */
0x00030000,
cifd->idEntries[i].bWidth,
cifd->idEntries[i].bHeight,
0
);
if (!hicon) {
FIXME("CreateIcon failed.\n");
return E_FAIL;
} else {
This->desc.picType = PICTYPE_ICON;
This->desc.u.icon.hicon = hicon;
This->origWidth = cifd->idEntries[i].bWidth;
This->origHeight = cifd->idEntries[i].bHeight;
hdcRef = CreateCompatibleDC(0);
This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
DeleteDC(hdcRef);
return S_OK;
}
}
/************************************************************************
* OLEPictureImpl_IPersistStream_Load (IUnknown)
*
* Loads the binary data from the IStream. Starts at current position.
* There appears to be an 2 DWORD header:
* DWORD magic;
* DWORD len;
*
* Currently implemented: BITMAP, ICON, JPEG, GIF
*/
static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
HRESULT hr = E_FAIL;
BOOL headerisdata = FALSE;
BOOL statfailed = FALSE;
ULONG xread, toread;
BYTE *xbuf;
DWORD header[2];
WORD magic;
STATSTG statstg;
OLEPictureImpl *This = impl_from_IPersistStream(iface);
TRACE("(%p,%p)\n",This,pStm);
/****************************************************************************************
* Part 1: Load the data
*/
/* Sometimes we have a header, sometimes we don't. Apply some guesses to find
* out whether we do.
*
* UPDATE: the IStream can be mapped to a plain file instead of a stream in a
* compound file. This may explain most, if not all, of the cases of "no
* header", and the header validation should take this into account.
* At least in Visual Basic 6, resource streams, valid headers are
* header[0] == "lt\0\0",
* header[1] == length_of_stream.
*
* Also handle streams where we do not have a working "Stat" method by
* reading all data until the end of the stream.
*/
hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
if (hr) {
TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
statfailed = TRUE;
/* we will read at least 8 byte ... just right below */
statstg.cbSize.QuadPart = 8;
}
hr=IStream_Read(pStm,header,8,&xread);
if (hr || xread!=8) {
FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
return hr;
}
headerisdata = FALSE;
xread = 0;
if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
toread = header[1];
} else {
if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
!memcmp(&(header[0]), "BM", 2) || /* BMP header */
!memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
(header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
(header[1]==0)
) {/* Incorrect header, assume none. */
headerisdata = TRUE;
toread = statstg.cbSize.QuadPart-8;
xread = 8;
} else {
FIXME("Unknown stream header magic: %08lx\n", header[0]);
toread = header[1];
}
}
if (statfailed) { /* we don't know the size ... read all we get */
int sizeinc = 4096;
int origsize = sizeinc;
ULONG nread = 42;
TRACE("Reading all data from stream.\n");
xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
if (headerisdata)
memcpy (xbuf, &header, 8);
while (1) {
while (xread < origsize) {
hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
xread+=nread;
if (hr || !nread)
break;
}
if (!nread || hr) /* done, or error */
break;
if (xread == origsize) {
origsize += sizeinc;
sizeinc = 2*sizeinc; /* exponential increase */
xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
}
}
if (hr)
TRACE("hr in no-stat loader case is %08lx\n", hr);
TRACE("loaded %ld bytes.\n", xread);
This->datalen = xread;
This->data = xbuf;
} else {
This->datalen = toread+(headerisdata?8:0);
xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
if (headerisdata)
memcpy (xbuf, &header, 8);
while (xread < This->datalen) {
ULONG nread;
hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
xread+=nread;
if (hr || !nread)
break;
}
if (xread != This->datalen)
FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
}
if (This->datalen == 0) { /* Marks the "NONE" picture */
This->desc.picType = PICTYPE_NONE;
return S_OK;
}
/****************************************************************************************
* Part 2: Process the loaded data
*/
magic = xbuf[0] + (xbuf[1]<<8);
switch (magic) {
case 0x4947: /* GIF */
hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
break;
case 0xd8ff: /* JPEG */
hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
break;
case 0x4d42: /* Bitmap */
hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
break;
case 0x0000: { /* ICON , first word is dwReserved */
hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
break;
}
default:
{
unsigned int i;
FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
hr=E_FAIL;
for (i=0;i<xread+8;i++) {
if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
else MESSAGE("%02x ",xbuf[i-8]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -