Windows 7 GdipCreateBitmapFromStream在Windows 7上更改合同?
我们有一个功能完善的应用程序,它刚刚在Windows7上崩溃,因为(GDI+原语)Windows 7 GdipCreateBitmapFromStream在Windows 7上更改合同?,windows-7,gdi+,Windows 7,Gdi+,我们有一个功能完善的应用程序,它刚刚在Windows7上崩溃,因为(GDI+原语)GdipCreateBitmapFromStream拒绝向它提供JPEG图像(在XP甚至Vista上都没有问题) 我们不直接调用GDI+,我们调用有文档记录的ATL CImage类,它调用该类,并获取错误 这是我们自己的OLE流实现 有人看到了解决这个问题的方法吗 下面是一个完整的测试用例: #include <atlbase.h> #include <atlimage.h> #includ
GdipCreateBitmapFromStream
拒绝向它提供JPEG图像(在XP甚至Vista上都没有问题)
我们不直接调用GDI+,我们调用有文档记录的ATL CImage类,它调用该类,并获取错误
这是我们自己的OLE流实现
有人看到了解决这个问题的方法吗
下面是一个完整的测试用例:
#include <atlbase.h>
#include <atlimage.h>
#include <gdiplus.h>
#include <time.h>
#include <sys/stat.h>
// GSMemoryStream.h : Declaration of the GSMemoryStream
/* No ATL or class factory support is needed here. You get one of these via "new", with zero reference count...
Image.Load(IStreamPtr(new GSMemoryStream(ptr, len));
and the smart pointer will provoke its deletion at the right time....
*/
// GSMemoryStream
class GSMemoryStream :
public IStream
{
private:
ULONG m_Length;
ULONG m_CurPtr;
PBYTE m_Base;
int m_rc;
public:
GSMemoryStream(PBYTE _p, DWORD _len) {
m_Length = _len;
m_CurPtr = 0;
m_Base = _p;
m_rc = 0;
}
GSMemoryStream () {
m_Length = 0;
m_CurPtr = 0;
m_Base = NULL;
m_rc = 0;
}
STDMETHODIMP Read(void *,ULONG,ULONG *);
STDMETHODIMP Write(const void *,ULONG,ULONG *) {return E_FAIL;}
STDMETHODIMP Seek(LARGE_INTEGER,DWORD,ULARGE_INTEGER *);
STDMETHODIMP SetSize(ULARGE_INTEGER) {return E_FAIL;}
STDMETHODIMP CopyTo(IStream *,ULARGE_INTEGER,ULARGE_INTEGER *,ULARGE_INTEGER *);
STDMETHODIMP Commit(DWORD) {return S_OK;}
STDMETHODIMP Revert(void) {return S_OK;}
STDMETHODIMP LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD) {return S_OK;}
STDMETHODIMP UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD) {return S_OK;}
STDMETHODIMP Stat(STATSTG *,DWORD);
STDMETHODIMP Clone(IStream ** ) {return E_FAIL;}
STDMETHODIMP QueryInterface(const IID & iid,void ** d) throw() {
if (IsEqualGUID(iid, IID_IUnknown) || IsEqualGUID (iid, __uuidof(IStream))) {
*d = (PVOID)this;
AddRef();
return S_OK;
}
return E_FAIL;
}
ULONG STDMETHODCALLTYPE AddRef(void) throw() {
m_rc++;
return S_OK;
}
ULONG STDMETHODCALLTYPE Release(void) throw() {
if (--m_rc == 0)
delete this; // can never go negative, because the m_rc won't be around any more once it is 0.
// so it's not even meaningful to test for it and breakpoint or throw.
return S_OK;
}
};
// CGSMemoryStream
STDMETHODIMP GSMemoryStream::Read(void * p,ULONG n, ULONG * pNread) {
ATLTRACE(L"GSMS$Read p %p bufct %d m_curptr %d\r\n", p, n, m_CurPtr);
if ((n + m_CurPtr) > m_Length)
n = m_Length - m_CurPtr;
memcpy(p, m_Base + m_CurPtr, n);
if (pNread)
*pNread = n;
m_CurPtr += n;
ATLTRACE(L"GSMS$Read(final) n %d m_CurPtr %d\r\n", n, m_CurPtr);
return S_OK;
}
STDMETHODIMP GSMemoryStream::Seek(LARGE_INTEGER pos,DWORD type,ULARGE_INTEGER * newpos) {
LONG lpos = (LONG)pos.LowPart;
ATLTRACE(L"GSMS$Seek type %d lpos %d m_CurPtr %d\r\n", type, lpos, m_CurPtr);
switch (type) {
case STREAM_SEEK_SET:
if (lpos < 0 || lpos > (LONG) m_Length)
return E_POINTER;
m_CurPtr = (ULONG)lpos;
break;
case STREAM_SEEK_CUR:
if (lpos + m_CurPtr < 0 || lpos + m_CurPtr > m_Length)
return E_POINTER;
m_CurPtr += lpos;
break;
case STREAM_SEEK_END:
if (lpos > 0)
lpos = -lpos;
if (lpos + m_Length < 0)
return E_POINTER;
m_CurPtr = m_Length + lpos;
break;
default:
return E_FAIL;
}
ATLTRACE(L"GSMS$Seek end m_CurPtr %d\r\n", m_CurPtr);
if (newpos) {
newpos->HighPart = 0;
newpos->LowPart = m_CurPtr;
}
return S_OK;
}
STDMETHODIMP GSMemoryStream::CopyTo(IStream * pstm,ULARGE_INTEGER cb,ULARGE_INTEGER * pNread,ULARGE_INTEGER * pNwritten){
ATLTRACE("GSMS$CopyTo\r\n");
if (cb.HighPart)
return E_INVALIDARG;
ULONG n = cb.LowPart;
if ((n + m_CurPtr) > m_Length)
n = m_Length - m_CurPtr;
ULONG nwritten = 0;
HRESULT hr = pstm->Write(m_Base+m_CurPtr, n, &nwritten);
if (nwritten < n)
nwritten = n;
if (pNread) {
pNread->HighPart = 0;
pNread->LowPart = n;
}
if (pNwritten) {
pNwritten->HighPart = 0;
pNwritten->LowPart = nwritten;
}
m_CurPtr += n;
return hr;
}
STDMETHODIMP GSMemoryStream::Stat(STATSTG * ps,DWORD krazyflag) {
ATLTRACE(L"GSMS$Stat kf %d\r\n", krazyflag);
memset(ps, 0, sizeof(STATSTG));
ps->type = STGTY_STREAM;
ps->cbSize.LowPart = m_Length;
ps->cbSize.HighPart = 0;
#if 0
ps->mtime = (DWORD)time(NULL);
ps->ctime = (DWORD)time(NULL);
ps->atime = (DWORD)time(NULL);
#endif
return S_OK;
}
int main (int argc, char ** argv) {
if (argc < 2) {
fprintf(stderr, "Need image file pathname\n");
exit(2);
}
struct _stat SSTAT;
const char* fn = argv[1];
int failed = _stat(fn, &SSTAT);
if (failed) {
fprintf(stderr, "Can't open file: %s\n", fn);
exit(3);
}
size_t len = SSTAT.st_size;
printf ("Len = %d\n", len);
FILE* f = fopen(fn, "rb");
unsigned char * buf = new unsigned char [len];
size_t got = fread (buf, 1, len, f);
printf ("Got = %d\n", got);
fclose(f);
CoInitialize(NULL);
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
GSMemoryStream G(buf, len);
CImage cim;
HRESULT hr = cim.Load(&G);
printf("HRESULT = 0x%08X\n", hr);
delete [] buf;
CoUninitialize();
return 0;
}
#包括
#包括
#包括
#包括
#包括
//GSMemoryStream.h:GSMemoryStream的声明
/*这里不需要ATL或类工厂支持。你可以通过“新建”得到其中一个,引用计数为零。。。
加载(IStreamPtr(新的GSMemoryStream(ptr,len));
智能指针将在正确的时间触发其删除。。。。
*/
//记忆流
GSMemoryStream类:
公共IStream
{
私人:
乌隆长度;
乌隆·穆库普特;
PBYTE m_碱;
国际货币联盟;
公众:
GSMemoryStream(PBYTE p,DWORD len){
m_长度=_长度;
m_CurPtr=0;
m_Base=_p;
m_rc=0;
}
GSMemoryStream(){
m_长度=0;
m_CurPtr=0;
m_Base=NULL;
m_rc=0;
}
STDMETHODIMP读取(void*、ULONG、ULONG*);
STDMETHODIMP Write(const void*,ULONG,ULONG*){return E_FAIL;}
STDMETHODIMP Seek(大整数、DWORD、大整数*);
STDMETHODIMP SetSize(ULARGE_INTEGER){返回E_FAIL;}
STDMETHODIMP CopyTo(IStream*,ULARGE_INTEGER,ULARGE_INTEGER*,ULARGE_INTEGER*);
STDMETHODIMP提交(DWORD){返回S_OK;}
STDMETHODIMP Revert(void){返回S_OK;}
STDMETHODIMP LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD){返回S_OK;}
STDMETHODIMP UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD){返回S_OK;}
标准方法统计(STATSTG*,DWORD);
STDMETHODIMP克隆(IStream**){返回E_FAIL;}
STDMETHODIMP查询接口(常量IID和IID,无效**d)抛出(){
如果(IsEqualGUID(iid,iid_IUnknown)| | IsEqualGUID(iid,iUIdof(IStream))){
*d=(PVOID)这个;
AddRef();
返回S_OK;
}
返回E_失败;
}
ULONG STDMETHODCALLTYPE AddRef(无效)抛出(){
m_rc++;
返回S_OK;
}
ULONG标准方法调用类型释放(无效)抛出(){
如果(--m_rc==0)
删除此;//永远不能变为负数,因为m_rc一旦变为0就不再存在。
//所以测试它和断点或抛出都没有意义。
返回S_OK;
}
};
//CGSMemoryStream
STDMETHODIMP GSMemoryStream::Read(void*p,ULONG n,ULONG*pNread){
ATLTRACE(L“GSMS$Read p%p bufct%d m_curptr%d\r\n”,p,n,m_curptr);
如果((n+m_CurPtr)>m_长度)
n=m_长度-m_电流;
memcpy(p,m_Base+m_CurPtr,n);
如果(pNread)
*pNread=n;
m_CurPtr+=n;
ATLTRACE(L“GSMS$Read(最终)n%d m\u CurPtr%d\r\n”,n,m\u CurPtr);
返回S_OK;
}
STDMETHODIMP GSMemoryStream::Seek(大整数位置,DWORD类型,ULARGE整数*新位置){
长LPO=(长)位置低部分;
ATLTRACE(L“GSMS$Seek type%d LPO%d m_CurPtr%d\r\n”,type,LPO,m_CurPtr);
开关(类型){
案例流搜索集:
如果(lpos<0 | | lpos>(长)m|u长度)
返回E_指针;
m_CurPtr=(ULONG)低截获概率;
打破
案例流_SEEK_CUR:
如果(lpos+m|u CurPtr<0 | lpos+m|u CurPtr>m|u长度)
返回E_指针;
m_CurPtr+=低截获概率;
打破
案例流_SEEK_END:
如果(lpos>0)
lpos=-lpos;
如果(lpos+m_长度<0)
返回E_指针;
m_CurPtr=m_长度+LPO;
打破
违约:
返回E_失败;
}
ATLTRACE(L“GSMS$Seek end m_CurPtr%d\r\n”,m_CurPtr);
if(新POS){
newpos->HighPart=0;
newpos->LowPart=m_CurPtr;
}
返回S_OK;
}
STDMETHODIMP GSMemoryStream::CopyTo(IStream*pstm、ULARGE_INTEGER cb、ULARGE_INTEGER*pNread、ULARGE_INTEGER*pnwrite){
ATLTRACE(“GSMS$CopyTo\r\n”);
如果(cb.高部分)
返回E_INVALIDARG;
ULONG n=cb.LowPart;
如果((n+m_CurPtr)>m_长度)
n=m_长度-m_电流;
ULONG nwrited=0;
HRESULT hr=pstm->Write(m_Base+m_CurPtr,n,&nwrited);
如果(nwritedHighPart=0;
pNread->LowPart=n;
}
如有(书面){
pnwrited->HighPart=0;
pnwrited->LowPart=nwrited;
}
m_CurPtr+=n;
返回人力资源;
}
STDMETHODIMP GSMemoryStream::Stat(STATSTG*ps,DWORD krazyflag){
ATLTRACE(L“GSMS$Stat kf%d\r\n”,krazyflag);
memset(ps,0,sizeof(STATSTG));
ps->type=STGTY\U流;
ps->cbSize.LowPart=m_长度;
ps->cbSize.HighPart=0;
#如果0
ps->mtime=(DWORD)时间(空);
ps->ctime=(DWORD)时间(空);
ps->atime=(DWORD)时间(空);
#恩迪夫
返回S_OK;
}
int main(int argc,字符**argv){
如果(argc<2){
fprintf(stderr,“需要图像文件路径名\n”);
出口(2);
}
结构统计数据;
常量字符*fn=argv[1];
int failed=_stat(fn和SSTAT);
如果(失败){
fprintf(stderr,“无法打开文件:%s\n”,fn);
出口(3);
}
尺寸长度=SSTAT.st\u尺寸;
printf(“Len=%d\n”,Len);
文件*f=fopen(fn,“rb”);
无符号字符*buf=新的无符号字符[len];
尺寸=fread(buf,1,len,f);
printf(“Got=%d\n”,Got);
fclose(f);
共初始化(空);
Gdiplus::GdiplusStartupInput GdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
GSMemoryStream G(buf,len);
CImage-cim;
HRESULT hr=cim.Load(&G)