IWinHttpRequest get_ResponseStream and Bitmap FromStream [modified]
-
Hi, I am writing some code that can download JPEG images from the net (HTTP) and display them on my dialog app. So far I am able to get the image with
IStream
interface by usingIWinHttpRequest
'sget_ResponseStream()
. But I found myself failing to take the Stream object to load it to GDI+ Bitmap object.IStream *pStream; // valid Stream object downloaded
if (NULL != pStream)
{
Bitmap *pGdiBmp = NULL;// Rewind IStream. LARGE\_INTEGER llMove; llMove.LowPart = 0; llMove.HighPart = 0; pStream->Seek(llMove, STREAM\_SEEK\_SET, NULL); pGdiBmp = Bitmap::FromStream(pStream);
}
pGdiBmp
is alwaysNULL
. I tried to save pStream to disk and the resulted binary is correct JPEG file. What am I doing wrong here? Any help would be great. Thanks in advance.modified on Thursday, May 7, 2009 11:48 AM
-
Hi, I am writing some code that can download JPEG images from the net (HTTP) and display them on my dialog app. So far I am able to get the image with
IStream
interface by usingIWinHttpRequest
'sget_ResponseStream()
. But I found myself failing to take the Stream object to load it to GDI+ Bitmap object.IStream *pStream; // valid Stream object downloaded
if (NULL != pStream)
{
Bitmap *pGdiBmp = NULL;// Rewind IStream. LARGE\_INTEGER llMove; llMove.LowPart = 0; llMove.HighPart = 0; pStream->Seek(llMove, STREAM\_SEEK\_SET, NULL); pGdiBmp = Bitmap::FromStream(pStream);
}
pGdiBmp
is alwaysNULL
. I tried to save pStream to disk and the resulted binary is correct JPEG file. What am I doing wrong here? Any help would be great. Thanks in advance.modified on Thursday, May 7, 2009 11:48 AM
I'd verify that the contents of the stream are a JPEG by loading it into memory using
GetHGlobalFromStream
followed by aGlobalLock
on theHGLOBAL
you got back from the first function. Then verify that the memory starts with the string "JFIF". I used the WinHttp functions to download a JPG and found that the JPG started after the first six bytes of the response (I created a stream on a set of bytes) - I needed to offset the stream by six bytes to get the Bitmap to load:Gdiplus::Bitmap* LoadBitmapFromUrl(CString const& url)
{
HINTERNET hInternet = WinHttpOpen(L"hello", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (!hInternet) return 0;
HINTERNET hConnection = WinHttpConnect(hInternet, L"www.python.org", INTERNET_DEFAULT_PORT, 0);
if (!hConnection) return 0;
LPCWSTR types[] = { L"image/jpeg", 0 };
HINTERNET hRequest = WinHttpOpenRequest(hConnection, L"GET", L"/images/success/standrews.jpg", 0, WINHTTP_NO_REFERER, types, 0);
if (!hRequest) return 0;
if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) return 0;
if (!WinHttpReceiveResponse(hRequest, 0)) return 0;
HGLOBAL gblBuffer = GlobalAlloc(0, 1<<20);
LPBYTE buffer = (LPBYTE)GlobalLock(gblBuffer);
DWORD nBytesRead;
if (!WinHttpReadData(hRequest, buffer, 1<<20, &nBytesRead)) return 0;
IStream* pStream = 0;
CreateStreamOnHGlobal(gblBuffer, FALSE, &pStream);
ULARGE_INTEGER size; size.QuadPart = nBytesRead;
pStream->SetSize(size);
LARGE_INTEGER offset; offset.QuadPart = 6;
pStream->Seek(offset, STREAM_SEEK_SET, 0);
return new Gdiplus::Bitmap(pStream, FALSE);
}(Please ignore the memory leak - I couldn't be bothered to tidy up - it's not production code :-))
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
-
I'd verify that the contents of the stream are a JPEG by loading it into memory using
GetHGlobalFromStream
followed by aGlobalLock
on theHGLOBAL
you got back from the first function. Then verify that the memory starts with the string "JFIF". I used the WinHttp functions to download a JPG and found that the JPG started after the first six bytes of the response (I created a stream on a set of bytes) - I needed to offset the stream by six bytes to get the Bitmap to load:Gdiplus::Bitmap* LoadBitmapFromUrl(CString const& url)
{
HINTERNET hInternet = WinHttpOpen(L"hello", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (!hInternet) return 0;
HINTERNET hConnection = WinHttpConnect(hInternet, L"www.python.org", INTERNET_DEFAULT_PORT, 0);
if (!hConnection) return 0;
LPCWSTR types[] = { L"image/jpeg", 0 };
HINTERNET hRequest = WinHttpOpenRequest(hConnection, L"GET", L"/images/success/standrews.jpg", 0, WINHTTP_NO_REFERER, types, 0);
if (!hRequest) return 0;
if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) return 0;
if (!WinHttpReceiveResponse(hRequest, 0)) return 0;
HGLOBAL gblBuffer = GlobalAlloc(0, 1<<20);
LPBYTE buffer = (LPBYTE)GlobalLock(gblBuffer);
DWORD nBytesRead;
if (!WinHttpReadData(hRequest, buffer, 1<<20, &nBytesRead)) return 0;
IStream* pStream = 0;
CreateStreamOnHGlobal(gblBuffer, FALSE, &pStream);
ULARGE_INTEGER size; size.QuadPart = nBytesRead;
pStream->SetSize(size);
LARGE_INTEGER offset; offset.QuadPart = 6;
pStream->Seek(offset, STREAM_SEEK_SET, 0);
return new Gdiplus::Bitmap(pStream, FALSE);
}(Please ignore the memory leak - I couldn't be bothered to tidy up - it's not production code :-))
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
Dear Stuart, Thanks for the help. I'd get invalid image if I offset the stream by 6 bytes. I am not sure why it worked in your case. Anyway, I found where my problem was. I have that code running outside of GDI+ library init scope. After I moved the following init code to
CWinApp::InitInstance()
, it worked fine.// Initialize GDI+.
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); -
Dear Stuart, Thanks for the help. I'd get invalid image if I offset the stream by 6 bytes. I am not sure why it worked in your case. Anyway, I found where my problem was. I have that code running outside of GDI+ library init scope. After I moved the following init code to
CWinApp::InitInstance()
, it worked fine.// Initialize GDI+.
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);I took it as a given that the GDI+ stuff was right - more fool me :-)
J.B. wrote:
I'd get invalid image if I offset the stream by 6 bytes. I am not sure why it worked in your case.
Maybe because I was using WinHttpReadData rather than getting a stream directly from the IWinHttpRequest object.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
-
I took it as a given that the GDI+ stuff was right - more fool me :-)
J.B. wrote:
I'd get invalid image if I offset the stream by 6 bytes. I am not sure why it worked in your case.
Maybe because I was using WinHttpReadData rather than getting a stream directly from the IWinHttpRequest object.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
Stuart Dootson wrote:
Maybe because I was using WinHttpReadData rather than getting a stream directly from the IWinHttpRequest object.
That'd be strange, because I checked the my Stream buffer and it had the same pattern as you described - after first 6 bytes, it comes with "JFIF"
FF D8 FF E0 00 10 4A 46 49 46
J F I F -
Stuart Dootson wrote:
Maybe because I was using WinHttpReadData rather than getting a stream directly from the IWinHttpRequest object.
That'd be strange, because I checked the my Stream buffer and it had the same pattern as you described - after first 6 bytes, it comes with "JFIF"
FF D8 FF E0 00 10 4A 46 49 46
J F I FI'm wrong - I thought the JFIF came at the start of a JPEG file - having just looked at a JPG in a hex editor, it doesn't.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p