📄 olepicture.c
字号:
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;
}
/*****************************************************
* start of PNG-specific code
* currently only supports colortype PNG_COLOR_TYPE_RGB
*/
#ifdef SONAME_LIBPNG
typedef struct{
ULONG position;
ULONG size;
BYTE * buff;
} png_io;
static void png_stream_read_data(png_structp png_ptr, png_bytep data,
png_size_t length)
{
png_io * io_ptr = png_ptr->io_ptr;
if(length + io_ptr->position > io_ptr->size){
length = io_ptr->size - io_ptr->position;
}
memcpy(data, io_ptr->buff + io_ptr->position, length);
io_ptr->position += length;
}
static void *libpng_handle;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(png_create_read_struct);
MAKE_FUNCPTR(png_create_info_struct);
MAKE_FUNCPTR(png_set_read_fn);
MAKE_FUNCPTR(png_read_info);
MAKE_FUNCPTR(png_read_image);
MAKE_FUNCPTR(png_get_rowbytes);
MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_destroy_read_struct);
MAKE_FUNCPTR(png_set_palette_to_rgb);
MAKE_FUNCPTR(png_read_update_info);
#undef MAKE_FUNCPTR
static void *load_libpng(void)
{
if((libpng_handle = wine_dlopen(SONAME_LIBPNG, RTLD_NOW, NULL, 0)) != NULL) {
#define LOAD_FUNCPTR(f) \
if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \
libpng_handle = NULL; \
return NULL; \
}
LOAD_FUNCPTR(png_create_read_struct);
LOAD_FUNCPTR(png_create_info_struct);
LOAD_FUNCPTR(png_set_read_fn);
LOAD_FUNCPTR(png_read_info);
LOAD_FUNCPTR(png_read_image);
LOAD_FUNCPTR(png_get_rowbytes);
LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_destroy_read_struct);
LOAD_FUNCPTR(png_set_palette_to_rgb);
LOAD_FUNCPTR(png_read_update_info);
#undef LOAD_FUNCPTR
}
return libpng_handle;
}
#endif /* SONAME_LIBPNG */
static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
{
#ifdef SONAME_LIBPNG
png_io io;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
INT row, rowsize, height, width;
png_bytep* row_pointers = NULL;
png_bytep pngdata = NULL;
BITMAPINFOHEADER bmi;
HDC hdcref = NULL;
HRESULT ret;
BOOL set_bgr = FALSE;
if(!libpng_handle) {
if(!load_libpng()) {
ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG);
return E_FAIL;
}
}
io.size = xread;
io.position = 0;
io.buff = xbuf;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
if(setjmp(png_jmpbuf(png_ptr))){
TRACE("Error in libpng\n");
ret = E_FAIL;
goto pngend;
}
info_ptr = ppng_create_info_struct(png_ptr);
ppng_set_read_fn(png_ptr, &io, png_stream_read_data);
ppng_read_info(png_ptr, info_ptr);
if(!(png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)){
FIXME("Unsupported .PNG type: %d\n", png_ptr->color_type);
ret = E_FAIL;
goto pngend;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE){
ppng_set_palette_to_rgb(png_ptr);
set_bgr = TRUE;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
set_bgr){
ppng_set_bgr(png_ptr);
}
ppng_read_update_info(png_ptr, info_ptr);
rowsize = ppng_get_rowbytes(png_ptr, info_ptr);
/* align rowsize to 4-byte boundary */
rowsize = (rowsize + 3) & ~3;
height = info_ptr->height;
width = info_ptr->width;
pngdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, height * rowsize);
row_pointers = HeapAlloc(GetProcessHeap(), 0, height * (sizeof(VOID *)));
if(!pngdata || !row_pointers){
ret = E_FAIL;
goto pngend;
}
for (row = 0; row < height; row++){
row_pointers[row] = pngdata + row * rowsize;
}
ppng_read_image(png_ptr, row_pointers);
bmi.biSize = sizeof(bmi);
bmi.biWidth = width;
bmi.biHeight = -height;
bmi.biPlanes = 1;
bmi.biBitCount = info_ptr->channels * 8;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = height * rowsize;
bmi.biXPelsPerMeter = 0;
bmi.biYPelsPerMeter = 0;
bmi.biClrUsed = 0;
bmi.biClrImportant = 0;
hdcref = GetDC(0);
This->desc.u.bmp.hbitmap = CreateDIBitmap(
hdcref,
&bmi,
CBM_INIT,
pngdata,
(BITMAPINFO*)&bmi,
DIB_RGB_COLORS
);
ReleaseDC(0, hdcref);
This->desc.picType = PICTYPE_BITMAP;
OLEPictureImpl_SetBitmap(This);
ret = S_OK;
pngend:
if(png_ptr)
ppng_destroy_read_struct(&png_ptr,
(info_ptr ? &info_ptr : (png_infopp) NULL),
(png_infopp)NULL);
HeapFree(GetProcessHeap(), 0, row_pointers);
HeapFree(GetProcessHeap(), 0, pngdata);
return ret;
#else /* SONAME_LIBPNG */
ERR("Trying to load PNG picture, but PNG supported not compiled in.\n");
return E_FAIL;
#endif
}
/*****************************************************
* start of Icon-specific code
*/
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;
}
}
static HRESULT OLEPictureImpl_LoadMetafile(OLEPictureImpl *This,
const BYTE *data, ULONG size)
{
HMETAFILE hmf;
HENHMETAFILE hemf;
/* SetMetaFileBitsEx performs data check on its own */
hmf = SetMetaFileBitsEx(size, data);
if (hmf)
{
This->desc.picType = PICTYPE_METAFILE;
This->desc.u.wmf.hmeta = hmf;
This->desc.u.wmf.xExt = 0;
This->desc.u.wmf.yExt = 0;
This->origWidth = 0;
This->origHeight = 0;
This->himetricWidth = 0;
This->himetricHeight = 0;
return S_OK;
}
hemf = SetEnhMetaFileBits(size, data);
if (!hemf) return E_FAIL;
This->desc.picType = PICTYPE_ENHMETAFILE;
This->desc.u.emf.hemf = hemf;
This->origWidth = 0;
This->origHeight = 0;
This->himetricWidth = 0;
This->himetricHeight = 0;
return S_OK;
}
/************************************************************************
* OLEPictureImpl_IPersistStream_Load (IUnknown)
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -