[shotwell] JPEG: Add fast file sniffer
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [shotwell] JPEG: Add fast file sniffer
- Date: Wed, 23 Oct 2019 18:38:12 +0000 (UTC)
commit 770de62f56f64652b2d538b88f4e64112382199f
Author: Jens Georg <mail jensge org>
Date: Wed Oct 23 20:34:43 2019 +0200
JPEG: Add fast file sniffer
Improves file browsing at least for the large JPEG case. If RAW files
are in the mix, it is still awfully slow.
Partially fix for #19
src/photos/JfifSupport.vala | 86 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 71 insertions(+), 15 deletions(-)
---
diff --git a/src/photos/JfifSupport.vala b/src/photos/JfifSupport.vala
index 5ea64a5b..967475ef 100644
--- a/src/photos/JfifSupport.vala
+++ b/src/photos/JfifSupport.vala
@@ -103,17 +103,68 @@ public class JfifSniffer : GdkSniffer {
}
public override DetectedPhotoInformation? sniff(out bool is_corrupted) throws Error {
+ is_corrupted = false;
+ if (!calc_md5) {
+ return fast_sniff (out is_corrupted);
+ } else {
+ if (!Jpeg.is_jpeg(file)) {
+ return null;
+ }
+
+ return base.sniff (out is_corrupted);
+
+ }
+ }
+
+ private DetectedPhotoInformation? fast_sniff(out bool is_corrupted) throws Error {
+ var detected = new DetectedPhotoInformation();
+
// Rely on GdkSniffer to detect corruption
is_corrupted = false;
-
- if (!Jpeg.is_jpeg(file))
- return null;
-
- DetectedPhotoInformation? detected = base.sniff(out is_corrupted);
- if (detected == null)
+
+ var fins = file.read(null);
+ var dins = new DataInputStream(fins);
+ dins.set_byte_order(DataStreamByteOrder.BIG_ENDIAN);
+
+ var marker = Jpeg.Marker.INVALID;
+ var length = Jpeg.read_marker_2(dins, out marker);
+
+ if (marker != Jpeg.Marker.SOI) {
+ is_corrupted = true;
return null;
-
+ }
+
+ length = Jpeg.read_marker_2(dins, out marker);
+ while (marker != Jpeg.Marker.SOF && length > 0) {
+ (dins as Seekable).seek(length, SeekType.CUR, null);
+ length = Jpeg.read_marker_2(dins, out marker);
+ }
+
+ if (marker == SOF) {
+ if (length < 6) {
+ is_corrupted = true;
+ return null;
+ }
+
+ // Skip precision
+ dins.read_byte();
+
+ // Next two 16 bytes are image dimensions
+ uint16 height = dins.read_uint16();
+ uint16 width = dins.read_uint16();
+
+ detected.image_dim = Dimensions(width, height);
+ detected.colorspace = Gdk.Colorspace.RGB;
+ detected.channels = 3;
+ detected.bits_per_channel = 8;
+ detected.format_name = "jpeg";
+ detected.file_format = PhotoFileFormat.from_pixbuf_name(detected.format_name);
+ } else {
+ is_corrupted = true;
+ }
+
return (detected.file_format == PhotoFileFormat.JFIF) ? detected : null;
+
}
}
@@ -152,6 +203,7 @@ namespace Jpeg {
SOI = 0xD8,
EOI = 0xD9,
+ SOF = 0xC0,
APP0 = 0xE0,
APP1 = 0xE1;
@@ -219,25 +271,22 @@ namespace Jpeg {
return is_jpeg_stream(mins);
}
- private int read_marker(InputStream fins, out Jpeg.Marker marker) throws Error {
+ private int32 read_marker_2(DataInputStream dins, out Jpeg.Marker marker) throws Error {
marker = Jpeg.Marker.INVALID;
-
- DataInputStream dins = new DataInputStream(fins);
- dins.set_byte_order(DataStreamByteOrder.BIG_ENDIAN);
-
+
if (dins.read_byte() != Jpeg.MARKER_PREFIX)
return -1;
marker = (Jpeg.Marker) dins.read_byte();
if ((marker == Jpeg.Marker.SOI) || (marker == Jpeg.Marker.EOI)) {
// no length
- return 0;
+ return -1;
}
uint16 length = dins.read_uint16();
- if (length < 2 && fins is Seekable) {
+ if (length < 2 && dins is Seekable) {
debug("Invalid length %Xh at ofs %" + int64.FORMAT + "Xh", length,
- (fins as Seekable).tell() - 2);
+ (dins as Seekable).tell() - 2);
return -1;
}
@@ -245,5 +294,12 @@ namespace Jpeg {
// account for two length bytes already read
return length - 2;
}
+
+ private int read_marker(InputStream fins, out Jpeg.Marker marker) throws Error {
+ DataInputStream dins = new DataInputStream(fins);
+ dins.set_byte_order(DataStreamByteOrder.BIG_ENDIAN);
+
+ return read_marker_2(dins, out marker);
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]