[diffoscope] 03/03: Add image metadata comparison.

Mattia Rizzolo mattia at debian.org
Sat Jan 14 12:01:57 CET 2017


This is an automated email from the git hooks/post-receive script.

mattia pushed a commit to branch master
in repository diffoscope.

commit 06e4ca7e88c8658590daad18cae2f82a614db2f8
Author: Maria Glukhova <siamezzze at gmail.com>
Date:   Fri Jan 13 15:46:40 2017 +0200

    Add image metadata comparison.
    
    Closes: #849395
    Signed-off-by: Mattia Rizzolo <mattia at debian.org>
---
 debian/control                           |   1 +
 diffoscope/comparators/image.py          |  36 +++++++++++++++++++++++++++++--
 diffoscope/exc.py                        |   4 ++++
 tests/comparators/test_ico_image.py      |  11 ++++++++++
 tests/comparators/test_jpeg_image.py     |  15 +++++++++++--
 tests/data/ico_image_meta_expected_diff  |  20 +++++++++++++++++
 tests/data/jpeg_image_meta_expected_diff |  26 ++++++++++++++++++++++
 tests/data/test1_meta.ico                | Bin 0 -> 6926 bytes
 tests/data/test1_meta.jpg                | Bin 0 -> 662 bytes
 tests/data/test2_meta.ico                | Bin 0 -> 3270 bytes
 tests/data/test2_meta.jpg                | Bin 0 -> 627 bytes
 11 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/debian/control b/debian/control
index 0d1a7a3..b96ebfc 100644
--- a/debian/control
+++ b/debian/control
@@ -23,6 +23,7 @@ Build-Depends:
  fp-utils <!nocheck>,
  ghc <!nocheck>,
  ghostscript <!nocheck>,
+ imagemagick <!nocheck>,
  libjs-jquery <!nocheck>,
  libjs-jquery-hotkeys <!nocheck>,
  libjs-jquery-isonscreen <!nocheck>,
diff --git a/diffoscope/comparators/image.py b/diffoscope/comparators/image.py
index bc8f069..b039362 100644
--- a/diffoscope/comparators/image.py
+++ b/diffoscope/comparators/image.py
@@ -28,6 +28,26 @@ from .utils.file import File
 from .utils.command import Command
 
 re_ansi_escapes = re.compile(r'\x1b[^m]*m')
+identify_attributes = '\n'.join(('Image format: %m',
+                                 'File size: %b',
+                                 'Height: %[height]',
+                                 'Width: %[width]',
+                                 'Orientation: %[orientation]',
+                                 'Compression type: %[compression]',
+                                 'Compression quality: %[quality]',
+                                 'Colorspace: %[colorspace]',
+                                 'Channels: %[channels]',
+                                 'Depth: %[depth]',
+                                 'Interlace mode: %[interlace]',
+                                 'Rendering intent: %[rendering-intent]',
+                                 'X resolution: %[resolution.x]',
+                                 'Y resolution: %[resolution.y]',
+                                 'Resolution units: %[units]',
+                                 'Transparency channel enabled: %A',
+                                 'Gamma: %[gamma]',
+                                 'Number of unique colors: %[colors]',
+                                 'Comment: %c',
+                                 'EXIF data: %[EXIF:*]'))
 
 
 class Img2Txt(Command):
@@ -44,6 +64,16 @@ class Img2Txt(Command):
         # Strip ANSI escapes
         return re_ansi_escapes.sub('', line.decode('utf-8')).encode('utf-8')
 
+class Identify(Command):
+    @tool_required('identify')
+    def cmdline(self):
+        return [
+            'identify',
+            '-format',
+            identify_attributes,
+            self.path,
+        ]
+
 class JPEGImageFile(File):
     RE_FILE_TYPE = re.compile(r'\bJPEG image data\b')
 
@@ -52,7 +82,8 @@ class JPEGImageFile(File):
         return JPEGImageFile.RE_FILE_TYPE.search(file.magic_file_type)
 
     def compare_details(self, other, source=None):
-        return [Difference.from_command(Img2Txt, self.path, other.path)]
+        return [Difference.from_command(Img2Txt, self.path, other.path),
+                Difference.from_command(Identify, self.path, other.path)]
 
 class ICOImageFile(File):
     RE_FILE_TYPE = re.compile(r'\bMS Windows icon resource\b')
@@ -68,7 +99,8 @@ class ICOImageFile(File):
         except subprocess.CalledProcessError:
             return []
 
-        return [Difference.from_command(Img2Txt, *xs)]
+        return [Difference.from_command(Img2Txt, *xs),
+                Difference.from_command(Identify, self.path, other.path)]
 
     @staticmethod
     @tool_required('icotool')
diff --git a/diffoscope/exc.py b/diffoscope/exc.py
index 0724a6b..b116ac8 100644
--- a/diffoscope/exc.py
+++ b/diffoscope/exc.py
@@ -84,6 +84,10 @@ class RequiredToolNotFound(Exception):
             'debian': 'gzip',
             'arch': 'gzip',
         },
+        'identify': {
+            'debian': 'imagemagick',
+            'arch': 'imagemagick',
+        },
         'img2txt': {
             'debian': 'caca-utils',
             'arch': 'libcaca',
diff --git a/tests/comparators/test_ico_image.py b/tests/comparators/test_ico_image.py
index d6ec6bb..a8decdd 100644
--- a/tests/comparators/test_ico_image.py
+++ b/tests/comparators/test_ico_image.py
@@ -26,6 +26,8 @@ from utils import skip_unless_tools_exist, data, load_fixture
 
 image1 = load_fixture(data('test1.ico'))
 image2 = load_fixture(data('test2.ico'))
+image1_meta = load_fixture(data('test1_meta.ico'))
+image2_meta = load_fixture(data('test2_meta.ico'))
 
 def test_identification(image1):
     assert isinstance(image1, ICOImageFile)
@@ -42,3 +44,12 @@ def differences(image1, image2):
 def test_diff(differences):
     expected_diff = open(data('ico_image_expected_diff')).read()
     assert differences[0].unified_diff == expected_diff
+
+ at pytest.fixture
+def differences_meta(image1_meta, image2_meta):
+    return image1_meta.compare(image2_meta).details
+
+ at skip_unless_tools_exist('img2txt', 'identify')
+def test_diff_meta(differences_meta):
+    expected_diff = open(data('ico_image_meta_expected_diff')).read()
+    assert differences_meta[-1].unified_diff == expected_diff
diff --git a/tests/comparators/test_jpeg_image.py b/tests/comparators/test_jpeg_image.py
index a731523..691b713 100644
--- a/tests/comparators/test_jpeg_image.py
+++ b/tests/comparators/test_jpeg_image.py
@@ -27,6 +27,8 @@ from utils import skip_unless_tools_exist, data, load_fixture
 
 image1 = load_fixture(data('test1.jpg'))
 image2 = load_fixture(data('test2.jpg'))
+image1_meta = load_fixture(data('test1_meta.jpg'))
+image2_meta = load_fixture(data('test2_meta.jpg'))
 
 def test_identification(image1):
     assert isinstance(image1, JPEGImageFile)
@@ -39,14 +41,23 @@ def test_no_differences(image1):
 def differences(image1, image2):
     return image1.compare(image2).details
 
- at skip_unless_tools_exist('img2txt')
+ at skip_unless_tools_exist('img2txt', 'identify')
 def test_diff(differences):
     expected_diff = open(data('jpeg_image_expected_diff')).read()
     assert differences[0].unified_diff == expected_diff
 
- at skip_unless_tools_exist('img2txt')
+ at skip_unless_tools_exist('img2txt', 'identify')
 def test_compare_non_existing(monkeypatch, image1):
     monkeypatch.setattr(Config(), 'new_file', True)
     difference = image1.compare(MissingFile('/nonexisting', image1))
     assert difference.source2 == '/nonexisting'
     assert len(difference.details) > 0
+
+ at pytest.fixture
+def differences_meta(image1_meta, image2_meta):
+    return image1_meta.compare(image2_meta).details
+
+ at skip_unless_tools_exist('img2txt', 'identify')
+def test_diff_meta(differences_meta):
+    expected_diff = open(data('jpeg_image_meta_expected_diff')).read()
+    assert differences_meta[-1].unified_diff == expected_diff
diff --git a/tests/data/ico_image_meta_expected_diff b/tests/data/ico_image_meta_expected_diff
new file mode 100644
index 0000000..4ec9309
--- /dev/null
+++ b/tests/data/ico_image_meta_expected_diff
@@ -0,0 +1,20 @@
+@@ -1,17 +1,17 @@
+ Image format: ICO
+-File size: 6.93KB
++File size: 3.27KB
+ Height: 100
+ Width: 100
+ Orientation: Undefined
+ Compression type: Undefined
+ Compression quality: 0
+ Colorspace: sRGB
+ Channels: srgba
+-Depth: 4
++Depth: 1
+ Interlace mode: None
+ Rendering intent: Perceptual
+ X resolution: 0
+ Y resolution: 0
+ Resolution units: Undefined
+ Transparency channel enabled: True
+ Gamma: 0.454545
diff --git a/tests/data/jpeg_image_meta_expected_diff b/tests/data/jpeg_image_meta_expected_diff
new file mode 100644
index 0000000..464a8af
--- /dev/null
+++ b/tests/data/jpeg_image_meta_expected_diff
@@ -0,0 +1,26 @@
+@@ -1,20 +1,20 @@
+ Image format: JPEG
+-File size: 662B
++File size: 627B
+ Height: 100
+ Width: 100
+ Orientation: Undefined
+ Compression type: JPEG
+-Compression quality: 90
++Compression quality: 95
+ Colorspace: sRGB
+ Channels: srgb
+ Depth: 8
+ Interlace mode: JPEG
+ Rendering intent: Perceptual
+-X resolution: 88
+-Y resolution: 88
++X resolution: 65
++Y resolution: 65
+ Resolution units: PixelsPerInch
+ Transparency channel enabled: False
+ Gamma: 0.454545
+ Number of unique colors: 1
+-Comment: Comment #1
++Comment: Comment #2
+ EXIF data: 
diff --git a/tests/data/test1_meta.ico b/tests/data/test1_meta.ico
new file mode 100644
index 0000000..8653da2
Binary files /dev/null and b/tests/data/test1_meta.ico differ
diff --git a/tests/data/test1_meta.jpg b/tests/data/test1_meta.jpg
new file mode 100644
index 0000000..335f368
Binary files /dev/null and b/tests/data/test1_meta.jpg differ
diff --git a/tests/data/test2_meta.ico b/tests/data/test2_meta.ico
new file mode 100644
index 0000000..2d207f1
Binary files /dev/null and b/tests/data/test2_meta.ico differ
diff --git a/tests/data/test2_meta.jpg b/tests/data/test2_meta.jpg
new file mode 100644
index 0000000..063b7da
Binary files /dev/null and b/tests/data/test2_meta.jpg differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list