In this tutorial (How To Capture Html Source Of A Web Page) we have learned to utilize IXmlHttpRequest to fetch html source of a web page. In that tutorial we can get the "text" which is the html source of a web page. As you already know, a web page might have one or more images. In that web page html source, the images will be represented by "links" to each image location. Armed with this information, can we get the real content of the image (using IXmlHttpRequest)?
The answer is simply yes.
Should you investigate IXmlHttpRequest closely, you would find that it has a property named responseStream. The official explanation says,
Represents only one of several forms in which the HTTP response can be returned.
Yeah, not very clear. I know. But if you read further down the page, you would find the remark that says,
Variant. The property is read-only. Represents the response entity body as an IStream. This stream returns the raw undecoded bytes as received directly from the server. Therefore, depending on what the server sent, this may appear as binary-encoded data (UTF-8, UCS-2, UCS-4, Shift_JIS, and so on).
Basically we can assume that if we ask an IXmlHttpRequest to fetch image content (which is binary), the content would probably returned in this property. And the next demo project proves that this assumption is correct.
Web Image Fetch Routine
I wrapped codes for fetching web images into a function which I named GetWebImageContent. It's implementation is shown below.
function GetWebImageContent(const AUrl: string; out AStream: TStream): Integer; var vUrl: WideString; vClient: IXMLHttpRequest; vBodyData: OleVariant; vJpeg: TJPEGImage; begin vUrl := Trim(LowerCase(AUrl)); if vUrl='' then raise Exception.Create('No URL specified'); // make sure that protocol prefix http:// always presents if (System.Pos('http://', vUrl) < 1) and (System.Pos('https://', vUrl) < 1) then vUrl := 'http://' + vUrl; // create the web client vClient := CoXMLHTTPRequest.Create; // initiate with type of operation we want the web client to do vClient.open('GET', vUrl, False, EmptyParam, EmptyParam); // Setup the initial body data to empty vBodyData := EmptyParam; // this is where the retrieval operation actually begin vClient.send(vBodyData); // enter the "wait" loop until the web client's complete the retrieval. // complete here can be a success or fail // Note that this is not necessary if we can use separate thread for fetching // the image content. It's actually recommended. repeat Application.ProcessMessages; Sleep(100); until vClient.readyState=4; Result := vClient.status; // we only create the stream if the fetching was a success (status equals 200) if vClient.status = 200 then AStream := TOleStream.Create(IUnknown(vClient.ResponseStream) as IStream) else AStream := nil; end;
- Open your Delphi IDE.
- Create a new project. Name it whatever you want. For this tutorial, I just named it Project1. Also I left the name of the autocreated form as is, i.e. Form1.
- Drop a TEdit, a TButton, and a TImage into Form1, and arrange them like shown below. Use all their default names, no need to change any of them.
- Copy and paste the GetWebImageContent function above into a place somewhere in Form1 unit.
- Double click on Button1 to generate skeleton code fot its OnClick event handler. Complete the skeleton using the following codes.
procedure TForm1.Button1Click(Sender: TObject); var S: TStream; vJpg: TJPEGImage; begin if GetWebImageContent(edtUrl.Text, S) = 200 then try vJpg := TJPEGImage.Create; try vJpg.LoadFromStream(S); Image1.Picture.Graphic := vJpg; finally vJpg.Free; end; finally S.Free; end; end;Note:
- make sure this event handler was written after GetWebImageContent function.
- You will need to add Jpeg unit into your uses list, since we are using TJpegImage class declared in it.
- If you have any question, feel free to post a reply
- Now let's run the project. Press F9 key to run the project from the IDE. Initially you will get something like shown below. (Note that the default image url was an image from one of my Arduino tutorial).
- Time to fetch the image content from the supplied url. Click on the button. After a while (depend on your internet connection speed), the image will be loaded into our Image1 control. Like shown below.
And here is full source code and executable sample of the demo project. Feel free to use and improve it.
GetWebImageContent.zip 260.6KB 1354 downloads