-
Notifications
You must be signed in to change notification settings - Fork 202
Avoid re-reading the image file on every scaled drawImage #3506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,6 +55,9 @@ | |
| */ | ||
| public class ImageLoader { | ||
|
|
||
| /** Upper bound on the bytes a format signature check may consume before the stream is rewound. */ | ||
| private static final int SIGNATURE_LOOKAHEAD_LIMIT = 8192; | ||
|
|
||
| /** | ||
| * the array of ImageData objects in this ImageLoader. | ||
| * This array is read in when the load method is called, | ||
|
|
@@ -209,16 +212,6 @@ List<ElementAtZoom<ImageData>> loadByZoom(String filename, int fileZoom, int tar | |
| return null; | ||
| } | ||
|
|
||
| ImageData loadBySize(String filename, int width, int height) { | ||
| if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); | ||
| try (InputStream stream = new FileInputStream(filename)) { | ||
| return loadBySize(stream, width, height); | ||
| } catch (IOException e) { | ||
| SWT.error(SWT.ERROR_IO, e); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| static boolean canLoadAtZoom(String filename, int fileZoom, int targetZoom) { | ||
| if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); | ||
| try (InputStream stream = new FileInputStream(filename)) { | ||
|
|
@@ -229,13 +222,29 @@ static boolean canLoadAtZoom(String filename, int fileZoom, int targetZoom) { | |
| return false; | ||
| } | ||
|
|
||
| static boolean isDynamicallySizable(String filename) { | ||
| try (InputStream stream = new FileInputStream(filename)) { | ||
| return FileFormat.isDynamicallySizableFormat(stream); | ||
| /** | ||
| * Loads the image at the given size if the file is a dynamically sizable format, | ||
| * reading the file only once for both the format check and the load. | ||
| */ | ||
| ImageDataLoader.AtSizeLoadResult loadBySizeIfDynamicallySizable(String filename, int width, int height) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When changing the usage protocol of ImageLoader for loading dynamically sizable image from file names, shouldn't we do the same for InputStreams for the sake of consistency? |
||
| if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); | ||
| try (InputStream stream = new BufferedInputStream(new FileInputStream(filename))) { | ||
| stream.mark(SIGNATURE_LOOKAHEAD_LIMIT); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this something the FileFormat should take care of? The lookahead limit just seems to be a guess and any future file format may require a different limit. Additionally, the SVG file format seems to require a much smaller lookahead right now. |
||
| Optional<Boolean> sizable = FileFormat.isDynamicallySizableFormatIfKnown(stream); | ||
| if (sizable.isEmpty()) { | ||
| return ImageDataLoader.AtSizeLoadResult.UNKNOWN_FORMAT; | ||
| } | ||
| if (!sizable.get()) { | ||
| return ImageDataLoader.AtSizeLoadResult.STATIC_FORMAT; | ||
| } | ||
| stream.reset(); | ||
| ImageData data = loadBySize(stream, width, height); | ||
| if (data == null) SWT.error(SWT.ERROR_INVALID_IMAGE); | ||
| return new ImageDataLoader.AtSizeLoadResult(Optional.of(data), false); | ||
| } catch (IOException e) { | ||
| SWT.error(SWT.ERROR_IO, e); | ||
| } | ||
| return false; | ||
| return ImageDataLoader.AtSizeLoadResult.UNKNOWN_FORMAT; | ||
| } | ||
|
|
||
| static boolean isDynamicallySizable(InputStream stream) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,8 +73,15 @@ private static Optional<FileFormat> determineFileFormat(LEDataInputStream stream | |
| private static final int MAX_SIGNATURE_BYTES = 18 + 2; // e.g. Win-BMP or OS2-BMP plus a safety-margin | ||
|
|
||
| public static boolean isDynamicallySizableFormat(InputStream is) { | ||
| Optional<FileFormat> format = determineFileFormat(new LEDataInputStream(is, MAX_SIGNATURE_BYTES)); | ||
| return format.isPresent() && !(format.get() instanceof StaticImageFileFormat); | ||
| return isDynamicallySizableFormatIfKnown(is).orElse(Boolean.FALSE); | ||
| } | ||
|
|
||
| /** | ||
| * @return empty if no format could be identified, so sizability is unknown | ||
| */ | ||
| public static Optional<Boolean> isDynamicallySizableFormatIfKnown(InputStream is) { | ||
| return determineFileFormat(new LEDataInputStream(is, MAX_SIGNATURE_BYTES)) | ||
| .map(format -> !(format instanceof StaticImageFileFormat)); | ||
|
Comment on lines
+76
to
+84
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just make the |
||
| } | ||
|
|
||
| static abstract class StaticImageFileFormat extends FileFormat { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really necessary to add yet another result type of image loading? We already have
ElementAtZoom. Introducing further times degrades comprehensibility.