Bug 224422 - [JFace] ImageDescriptor.createFromURL should use faster image loading
Summary: [JFace] ImageDescriptor.createFromURL should use faster image loading
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 M7   Edit
Assignee: Tod Creasey CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 225182
  Show dependency tree
 
Reported: 2008-03-27 13:20 EDT by Chris Grindstaff CLA
Modified: 2010-09-15 06:29 EDT (History)
6 users (show)

See Also:
Tod_Creasey: review? (john.arthorne)


Attachments
patch (10.04 KB, patch)
2008-03-28 14:54 EDT, Tod Creasey CLA
no flags Details | Diff
Strip leading slash (1.80 KB, patch)
2008-04-16 08:54 EDT, Chris Grindstaff CLA
no flags Details | Diff
Updated patch (2.74 KB, patch)
2008-04-16 11:50 EDT, Tod Creasey CLA
no flags Details | Diff
Small refinement (2.97 KB, patch)
2008-04-16 12:05 EDT, Tod Creasey CLA
no flags Details | Diff
R 3.3.2 version (7.18 KB, application/octet-stream)
2008-04-22 14:45 EDT, Tod Creasey CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Grindstaff CLA 2008-03-27 13:20:53 EDT
Build ID: I20080207-1530

Steps To Reproduce:
This is related to bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=219432
Bug 219432 improved image loading performance by using SWTs native OS image loading code.

ImageDescriptor.createFromURL(imgURL) should sniff the URL to exploit the improvement in FileImageDescriptor.

Something along the lines of:
URL imgURL = new URL("big.png");
URL local = FileLocator.toFileURL(imgURL);
ImageDescriptor imgDesc;
if(local.getProtocol().equals("file"))
  imgDesc = ImageDescriptor.createFromFile(null, local.toExternalForm().substring(6)); // "file://".length()
else 
  imgDesc = ImageDescriptor.createFromURL(FileLocator.resolve(imgURL));
themeImg = imgDesc.createImage(false);

More information:
Comment 1 Tod Creasey CLA 2008-03-28 14:54:02 EDT
Created attachment 94036 [details]
patch

Here is an OSGI friendly patch. I am currently not happy with this as we are trying to open files first and then falling through to the URL stream loading. I would prefer if there was a better way to introspect the URL.

See the example snippet which loads from a file and an http URL.
Comment 2 Tod Creasey CLA 2008-03-28 15:07:38 EDT
I would like some advice from John and Szymon as they are the resource guys.
Comment 3 John Arthorne CLA 2008-03-31 10:56:11 EDT
This doesn't seem relate to resources, but the only advice I have is to introspect the protocol rather than directly trying to interpret URL.getPath():

String path = null;
if ("file".equalsIgnoreCase(url.getProtocol())) {
  path = url.getPath();
if (path != null) {
   .. use file loading
} else {
   .. use URL stream loading ...
}

Comment 4 Tod Creasey CLA 2008-04-02 11:10:11 EDT
John does this handle the OSGi case where the protocol is bundle.

i.e. should I do this check only if there is no OSGi and if there is can I just rely on FileLocator?
Comment 5 John Arthorne CLA 2008-04-03 09:44:42 EDT
> should I do this check only if there is no OSGi and if there is can I just
rely on FileLocator?

I would do this check both in the non-OSGi case, and on the URL returned from FileLocator#toFileURL().  Note toFileURL says "@return the converted file URL or the original URL passed in if it is not recognized by this converter", so you can't assume that it will always be a file: URL you get back.
Comment 6 Tod Creasey CLA 2008-04-03 10:37:24 EDT
Fixed with John's suggestions in build >20080403
Comment 7 Chris Grindstaff CLA 2008-04-15 16:08:54 EDT
Todd, I back-ported your patch to Eclipse 3.2.2 and in the process noticed that it's not actually making use of the faster SWT image loading due to a path issue.
In FileImageDescriptor and URLImageDescriptor getPath() returns a path that looks like this on Windows. /c:/temp/a.png. 

Image(Device,String) doesn't like that path, no exceptions of course, it just takes the slow path instead.

When I trim the leading slash i.e. c:/temp/a.png the fast path is chosen and I see ~50% improvement to image loading.

I'm using locatedURL.getPath().substring(1); seem reasonable?
Comment 8 Tod Creasey CLA 2008-04-15 16:43:46 EDT
Chris if you could attach a new patch that would be really useful.
Comment 9 Chris Grindstaff CLA 2008-04-16 08:54:09 EDT
Created attachment 96248 [details]
Strip leading slash

Seems safer to only strip the leading slash as opposed to always doing a substring(1). I've only tried this on Windows. I'm not sure if the other platforms have a similar SWT API to even call.
Comment 10 Tod Creasey CLA 2008-04-16 11:32:52 EDT
The trim is only correct on Windows - a leading slash is correct on a Unix based platform so stripping the / is not the right answer.

However you are right that we need to remove it on Windows. Szymon or John what is recommended approach to doing this?
Comment 11 Tod Creasey CLA 2008-04-16 11:50:42 EDT
Created attachment 96273 [details]
Updated patch

This patch uses the same idea but processes using the Path object so as to get correct behaviour on all platforms.

I have also added a failsafe for FileImageDescriptor that calls the slower getStream SWT API when we fail as I did for URLImageDescriptor. This should solve the exception we are seeing in Bug 225182.

Chris I would appreciate it if you could check this out.
Comment 12 Tod Creasey CLA 2008-04-16 12:05:33 EDT
Created attachment 96277 [details]
Small refinement

Due to one missed case. Released to HEAD for build >20080416 but I will leave this open pending confirmation from Chris.
Comment 13 Chris Grindstaff CLA 2008-04-16 13:53:41 EDT
Tod - I grabbed head, applied to my environment and and looks/works great.
Comment 14 B. Chen CLA 2008-04-21 14:51:33 EDT
When this fix is made, we are also interest in back porting to Eclipse 3.2.2
Comment 15 Mike Wilson CLA 2008-04-22 12:13:29 EDT
Tod, how hard would it be to build a 3.2.2 patch for this?

Comment 16 Tod Creasey CLA 2008-04-22 14:16:22 EDT
It is one class so just loading the 3.4 version into 3.3.2 and creating a patch should be all you need.
Comment 17 Tod Creasey CLA 2008-04-22 14:33:10 EDT
Marking FIXED
Comment 18 Tod Creasey CLA 2008-04-22 14:45:00 EDT
Created attachment 97067 [details]
R 3.3.2 version

Here is a 3.3.2 version. it uses the pre 3.4 error reporting as well.
Comment 19 B. Chen CLA 2008-04-23 11:27:01 EDT
Hi Tod, we need to back port to Eclipse 3.2.2 release, just want to make sure your patch is for 3.2.2 or 3.3.2?
Comment 20 Tod Creasey CLA 2008-04-23 11:36:16 EDT
That is a 3.3.2 patch - you would likely need a different one for 3.3.2 but it would have the same code content I would think.

Comment 21 B. Chen CLA 2008-04-23 12:04:24 EDT
Hi Tod, thanks for quick response, could you please provide a patch for 3.2.2?
Comment 22 Tod Creasey CLA 2008-04-23 13:31:31 EDT
The problem with using 3.2.2 is that getFilePath() references the JFaceActivator which was not added until 3.3.

Here is the code. John can you think of an alternative way to determine if OSGi is present? Here is the code in question.

if (JFaceActivator.getBundleContext() == null) {
    if (FILE_PROTOCOL.equalsIgnoreCase(url.getProtocol()))
	return new Path(url.getFile()).toOSString();
	return null;
}

URL locatedURL = FileLocator.toFileURL(url);
   if (FILE_PROTOCOL.equalsIgnoreCase(locatedURL.getProtocol()))
	return new Path(locatedURL.getPath()).toOSString();

return null;
Comment 23 Tod Creasey CLA 2008-04-29 13:35:32 EDT
Verified in I20080428-0100