IPicture中的装载图片OleLoadPicture失败

Ginie 2011-09-01 10:16:30
我从内存中读取一个已存好的图片,然后在OnPaint中调用下面的IPicture方法,返回出错,代码如下

void CTHIRD::showpic(BYTE *pMemData, DWORD len)
{
IStream *m_pStream;
IPicture *m_pPictrue;
OLE_XSIZE_HIMETRIC m_JPGWidth;
OLE_YSIZE_HIMETRIC m_JPGHeight;
HGLOBAL hMem;

hMem=GlobalAlloc(GMEM_MOVEABLE,len);
LPVOID pData=NULL;
pData=GlobalLock(hMem);
memcpy(pData, pMemData, len);
GlobalUnlock(hMem);
CreateStreamOnHGlobal(hMem,TRUE,&m_pStream);
if(SUCCEEDED(OleLoadPicture(m_pStream,len,TRUE,IID_IPicture,(LPVOID*)&m_pPictrue)))
{
m_pPictrue->get_Height(&m_JPGHeight);
m_pPictrue->get_Width(&m_JPGWidth);
CRect lpRec;
GetDlgItem(IDC_STATIC1)->GetWindowRect(&lpRec);
ScreenToClient(&lpRec);
m_pPictrue->Render(GetDC()->m_hDC,lpRec.left,lpRec.top
,(int)(m_JPGWidth/26.45), (int)(m_JPGHeight/26.45)
,0 ,m_JPGHeight, m_JPGWidth,-m_JPGHeight,NULL);

}
}

程序不会进那个if里面,返回的是失败,如果我把if去掉,调式就会出现下面的问题,内存读取错误,定位到
...全文
947 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
sac_meTeor 2014-05-15
  • 打赏
  • 举报
回复
现在也遇到这样的问题, 代码以前是可以的, 在XP下, 但是现在还了Win7就不行了
WF1986 2014-02-28
  • 打赏
  • 举报
回复
我现在也遇到这样的问题,我是直接读的图片文件,但是我的只要用美图秀秀把文件重新保存一下就可以,现在也在纠结,谁能解决这个问题
bluerain159 2013-10-31
  • 打赏
  • 举报
回复
试试先不把pIPicture 初始化为NULL。
  • 打赏
  • 举报
回复
请问一下你的问题解决没?我最近和你的问题一样,不知道你是如何解决的呀? OleLoadPicture(pIStream, 0, false, IID_IPicture, (LPVOID*)&(pIPicture))这个函数执行后 pIPicture 为0
zpp19890312 2012-07-18
  • 打赏
  • 举报
回复
我也发生了同样的问题,试了上面的办法都没有成功,最后发现是图像数据出现问题,memcpy中的,最后解决了
sclz 2011-11-28
  • 打赏
  • 举报
回复
悲剧的看不到,居然。
Ginie 2011-09-01
  • 打赏
  • 举报
回复
showpic这个方法应该没有问题,是不是我抓取图片到内存中出现了问题呢,我抓取图片的方法用的是directshow的一个例子,代码如下

bool CDXGraph::SnapshotBitmap(const char *outFile)
{

if (mBasicVideo) // 类IBasicVideo
{
long bitmapSize = 0;
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, 0)))
{
bool pass = false;
unsigned char * buffer = new unsigned char[bitmapSize];
// 得到当前画面的大小bitmapSize和数据buffer
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, (long *)buffer)))
{
newbuffer = buffer;
newbitmapSize = bitmapSize;
/* BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;

lpbi = (LPBITMAPINFOHEADER)buffer;

int nColors = 0; //调色板中的颜色个数.(RGB格式在8位以下的,需要用调色板。
//调色板实际上就是定义一些颜色的数组)
if (lpbi->biBitCount <= 8) //biBitCount:每个像素的位数.PS:RGB32每个像素用32位表示,也就是4个字节
nColors = 1 << lpbi->biBitCount;

hdr.bfType = ((WORD) ('M' << 8) | 'B'); //always is "BM"
hdr.bfSize = bitmapSize + sizeof( hdr );
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize +
nColors * sizeof(RGBQUAD));

CString FileName;//建立文件
FileName.Format("Frame-%05d.bmp",i);
//CString strtemp = strBmpDir;
//strtemp += "\\";
//strtemp += FileName;
FILE* fp=_tfopen(FileName ,_T("wb"));
fwrite(&hdr,1,sizeof(BITMAPFILEHEADER),fp);//写入文件头

fwrite(lpbi,1,sizeof(BITMAPINFOHEADER),fp);//写入信息头

int ff = fwrite(buffer,1,lpbi->biSizeImage,fp);
int e = GetLastError();
pass=true;
fclose(fp);


// szTemp[] = "C:\\mysnapshot.bmp"临时的.bmp文件(outFile指针所指)
/* CFile bitmapFile(outFile, CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
bitmapFile.Write(&hdr, sizeof(BITMAPFILEHEADER)); // 设置.bmp格式
bitmapFile.Write(buffer, bitmapSize); // 存入数据(通俗的说就是画图)
bitmapFile.Close(); // Closes the bitmapFile and deletes the object*/
pass = true;
}
delete [] buffer;
return pass;
}
}
return false;
}

我不需要生成图片到文磁盘中,所以我把下面的方法注释掉了,newbuffer , newbitmapSize,是我申明的全局变量,用来从其他类中获取图片数据的,这样获取有问题么
Ginie 2011-09-01
  • 打赏
  • 举报
回复
我看了资料,资料说这是因为图片的无效性造成的,因为我是直接捕捉视频帧图像的,我用的那个buffer可以直接生成图片到文件中保存,应该问题不大啊,我只是把后面生成图片的步骤去掉了,只留下获取到的内存数据,然后读这个内存数据图像的啊,怎么会无效呀
Ginie 2011-09-01
  • 打赏
  • 举报
回复
我用了一个HRESULT来接收这个,返回-2146827807,我也试了下,返回的结果S_OK,E_NOINTERFACE,E_POINTER都不是
gameslq 2011-09-01
  • 打赏
  • 举报
回复
检查下函数的OleLoadPicture返回值

This function OleLoadPicture returns S_OK on success. Other possible values include the following.

Return code Description
E_NOINTERFACE The object does not support the specified interface.
E_POINTER The stream is not valid. For example, it may be NULL.

诶呦 2011-09-01
  • 打赏
  • 举报
回复
一共能影响的代码就那么几句
同意楼上的先看看CreateStreamOnHGlobal
WINOLEAPI CreateStreamOnHGlobal(   
HGLOBAL hGlobal, //Memory handle for the stream object   
BOOL fDeleteOnRelease, //Whether to free memory when the object is released   LPSTREAM *ppstm //Address of output variable that receives the IStream interface pointer );
如果函数创建流对象成功则返回S_OK。
Ginie 2011-09-01
  • 打赏
  • 举报
回复

if(SUCCEEDED(CreateStreamOnHGlobal(hMem,true,&m_pStream)))
{
m_pPicture = NULL;
if(SUCCEEDED(OleLoadPicture(m_pStream,0,FALSE,IID_IPicture,(LPVOID*)&(m_pPicture))))
{
m_pPicture->get_Height(&m_JPGHeight);
m_pPicture->get_Width(&m_JPGWidth);
CRect lpRec;
GetDlgItem(IDC_STATIC1)->GetWindowRect(&lpRec);
ScreenToClient(&lpRec);
m_pPicture->Render(GetDC()->m_hDC,lpRec.left,lpRec.top
,(int)(m_JPGWidth/26.45), (int)(m_JPGHeight/26.45)
,0 ,m_JPGHeight, m_JPGWidth,-m_JPGHeight,NULL);

}

CreateStreamOnHGlobal这个方法正常运行下去了,而且m_stream都有值了,真的好奇怪
gameslq 2011-09-01
  • 打赏
  • 举报
回复
第一步:检查参考CreateStreamOnHGlobal用法,检查下该函数的返回值
并根据返回值检查下问题所在
Ginie 2011-09-01
  • 打赏
  • 举报
回复
对了,我把图片保存到内存中是这样保存的

bool CDXGraph::SnapshotBitmap(const char *outFile)
{

if (mBasicVideo) // 类IBasicVideo
{
long bitmapSize = 0;
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, 0)))
{
bool pass = false;
unsigned char * buffer = new unsigned char[bitmapSize];
// 得到当前画面的大小bitmapSize和数据buffer
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, (long *)buffer)))
{
newbuffer = buffer;
newbitmapSize = bitmapSize;
Ginie 2011-09-01
  • 打赏
  • 举报
回复
我把调试的每一步都截图了,麻烦大家帮我看看是哪的错误呀,谢谢了








Ginie 2011-09-01
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 gameslq 的回复:]
CreateStreamOnHGlobal(hMem,TRUE,&m_pStream);
改为
CreateStreamOnHGlobal(pData,FALSE,&m_pStream);
[/Quote]
还是不行呢,我把程序改了

IStream *m_pStream;
IPicture *m_pPictrue;
OLE_XSIZE_HIMETRIC m_JPGWidth;
OLE_YSIZE_HIMETRIC m_JPGHeight;
HGLOBAL hMem;

hMem=GlobalAlloc(GMEM_MOVEABLE,len);
LPVOID pData=NULL;
pData=GlobalLock(hMem);
memcpy(pData, pMemData, len);
GlobalUnlock(hMem);
CreateStreamOnHGlobal(pData,FALSE,&m_pStream);
m_pPictrue = NULL;
if(SUCCEEDED(OleLoadPicture(m_pStream,0,FALSE,IID_IPicture,(LPVOID*)&(m_pPictrue))))
{
m_pPictrue->get_Height(&m_JPGHeight);
m_pPictrue->get_Width(&m_JPGWidth);
CRect lpRec;
GetDlgItem(IDC_STATIC1)->GetWindowRect(&lpRec);
ScreenToClient(&lpRec);
m_pPictrue->Render(GetDC()->m_hDC,lpRec.left,lpRec.top
,(int)(m_JPGWidth/26.45), (int)(m_JPGHeight/26.45)
,0 ,m_JPGHeight, m_JPGWidth,-m_JPGHeight,NULL);

结果还是那个问题呢
gameslq 2011-09-01
  • 打赏
  • 举报
回复
CreateStreamOnHGlobal(hMem,TRUE,&m_pStream);
改为
CreateStreamOnHGlobal(pData,FALSE,&m_pStream);
Ginie 2011-09-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 visualeleven 的回复:]
C/C++ code
/*
  *如下代码段实现的功能是从指定的路径中读取图片,并显示出来
  */
  void DisplayImage(HDC hDC, LPCTSTR szImagePath)
  {
  HANDLE hFile=CreateFile(szImagePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING……
[/Quote]
我也是这样做的,只不过我的不是从文件位置读取,我的是用DS做的视频回放的程序,回放过程中将当前帧的图片保存在内存中,而且这个也得到了,就是在 if(SUCCEEDED(OleLoadPicture(m_pStream,len,TRUE,IID_IPicture,(LPVOID*)&m_pPictrue)))这个地方,我调式后这里的m_pPictrue是0,为什么这里我不能得到m_pPicture呢
Eleven 2011-09-01
  • 打赏
  • 举报
回复
/*
  *如下代码段实现的功能是从指定的路径中读取图片,并显示出来
  */
  void DisplayImage(HDC hDC, LPCTSTR szImagePath)
  {
  HANDLE hFile=CreateFile(szImagePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //从指定的路径szImagePath中读取文件句柄
  DWORD dwFileSize=GetFileSize(hFile, NULL); //获得图片文件的大小,用来分配全局内存
  HGLOBAL hImageMemory=GlobalAlloc(GMEM_MOVEABLE, dwFileSize); //给图片分配全局内存
  void *pImageMemory=GlobalLock(hImageMemory); //锁定内存
  DWORD dwReadedSize; //保存实际读取的文件大小
  ReadFile(hFile, pImageMemory, dwFileSize, &dwReadedSize, NULL); //读取图片到全局内存当中
  GlobalUnlock(hImageMemory); //解锁内存
  CloseHandle(hFile); //关闭文件句柄
  IStream *pIStream;//创建一个IStream接口指针,用来保存图片流
  IPicture *pIPicture;//创建一个IPicture接口指针,表示图片对象
  CreateStreamOnHGlobal(hImageMemory, false, &pIStream) //用全局内存初使化IStream接口指针
  OleLoadPicture(pIStream, 0, false, IID_IPicture, (LPVOID*)&(pIPicture));//用OleLoadPicture获得IPicture接口指针
  //得到IPicture COM接口对象后,你就可以进行获得图片信息、显示图片等操作
  OLE_XSIZE_HIMETRIC hmWidth;
  OLE_YSIZE_HIMETRIC hmHeight;
  pIPicture->get_Width(&hmWidth); //用接口方法获得图片的宽和高
  pIPicture->get_Height(&hmHeight);
  pIPicture->Render(hDC,0,0,100,100,0,hmHeight,hmWidth,-hmHeight,NULL); //在指定的DC上绘出图片
  GlobalFree(hImageMemory); //释放全局内存
  pIStream->Release(); //释放pIStream
  pIPicture->Release(); //释放pIPicture
  }
LiuYinChina 2011-09-01
  • 打赏
  • 举报
回复
http://blog.csdn.net/robertbaker/article/details/4136888
加载更多回复(5)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧