summaryrefslogtreecommitdiff
path: root/src/photos/GdkSupport.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/photos/GdkSupport.vala')
-rw-r--r--src/photos/GdkSupport.vala28
1 files changed, 26 insertions, 2 deletions
diff --git a/src/photos/GdkSupport.vala b/src/photos/GdkSupport.vala
index f7e18d5..64a08d6 100644
--- a/src/photos/GdkSupport.vala
+++ b/src/photos/GdkSupport.vala
@@ -21,7 +21,30 @@ public abstract class GdkReader : PhotoFileReader {
}
public override Gdk.Pixbuf scaled_read(Dimensions full, Dimensions scaled) throws Error {
- return new Gdk.Pixbuf.from_file_at_scale(get_filepath(), scaled.width, scaled.height, false);
+ Gdk.Pixbuf result = null;
+ /* if we encounter a situation where there are two orders of magnitude or more of
+ difference between the full image size and the scaled size, and if the full image
+ size has five or more decimal digits of precision, Gdk.Pixbuf.from_file_at_scale( ) can
+ fail due to what appear to be floating-point round-off issues. This isn't surprising,
+ since 32-bit floats only have 6-7 decimal digits of precision in their mantissa. In
+ this case, we prefetch the image at a larger scale and then downsample it to the
+ desired scale as a post-process step. This short-circuits Gdk.Pixbuf's buggy
+ scaling code. */
+ if (((full.width > 9999) || (full.height > 9999)) && ((scaled.width < 100) ||
+ (scaled.height < 100))) {
+ Dimensions prefetch_dimensions = full.get_scaled_by_constraint(1000,
+ ScaleConstraint.DIMENSIONS);
+
+ result = new Gdk.Pixbuf.from_file_at_scale(get_filepath(), prefetch_dimensions.width,
+ prefetch_dimensions.height, false);
+
+ result = result.scale_simple(scaled.width, scaled.height, Gdk.InterpType.HYPER);
+ } else {
+ result = new Gdk.Pixbuf.from_file_at_scale(get_filepath(), scaled.width,
+ scaled.height, false);
+ }
+
+ return result;
}
}
@@ -112,13 +135,14 @@ public abstract class GdkSniffer : PhotoFileSniffer {
Gdk.Pixbuf? pixbuf = pixbuf_loader.get_pixbuf();
if (pixbuf == null)
return;
-
+
detected.colorspace = pixbuf.get_colorspace();
detected.channels = pixbuf.get_n_channels();
detected.bits_per_channel = pixbuf.get_bits_per_sample();
unowned Gdk.PixbufFormat format = pixbuf_loader.get_format();
detected.format_name = format.get_name();
+ debug("Pixbuf detected format name: %s", detected.format_name);
detected.file_format = PhotoFileFormat.from_pixbuf_name(detected.format_name);
area_prepared = true;