Commit a7452e87 authored by Maria Glukhova's avatar Maria Glukhova

Add visual comparison for PNG and static GIF images.

For PNG and static GIF images, add the same types of comparison as for
JPG and ICO, but output them alongside with text difference to not lose
metadata information.
Also, do not even construct visual differences if they are not going
to be used (no HTML output).
parent 7a067c82
......@@ -18,12 +18,18 @@
# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
import re
import subprocess
import logging
from diffoscope.tools import tool_required
from diffoscope.difference import Difference
from diffoscope.config import Config
from .utils.file import File
from .utils.command import Command
from .image import pixel_difference, flicker_difference, get_image_size
logger = logging.getLogger(__name__)
class Gifbuild(Command):
......@@ -41,14 +47,37 @@ class Gifbuild(Command):
return b""
return line
@tool_required('identify')
def is_image_static(image_path):
return subprocess.check_output(('identify', '-format',
'%n', image_path)) == b'1'
class GifFile(File):
RE_FILE_TYPE = re.compile(r'^GIF image data\b')
def compare_details(self, other, source=None):
return [Difference.from_command(
gifbuild_diff = Difference.from_command(
Gifbuild,
self.path,
other.path,
source='gifbuild',
)]
)
differences = [gifbuild_diff]
if (gifbuild_diff is not None) and Config().html_output and \
(get_image_size(self.path) == get_image_size(other.path)):
try:
own_size = get_image_size(self.path)
other_size = get_image_size(other.path)
self_static = is_image_static(self.path)
other_static = is_image_static(other.path)
if (own_size == other_size) and self_static and other_static:
logger.debug('Generating visual difference for %s and %s',
self.path, other.path)
content_diff = Difference(None, self.path, other.path,
source='Image content')
content_diff.add_visuals([pixel_difference(self.path, other.path),
flicker_difference(self.path, other.path)])
differences.append(content_diff)
except subprocess.CalledProcessError: #noqa
pass
return differences
......@@ -20,16 +20,20 @@
import re
import subprocess
import base64
import logging
from diffoscope.tools import tool_required
from diffoscope.tempfiles import get_named_temporary_file
from diffoscope.difference import Difference, VisualDifference
from diffoscope.config import Config
from .utils.file import File
from .utils.command import Command
re_ansi_escapes = re.compile(r'\x1b[^m]*m')
logger = logging.getLogger(__name__)
class Img2Txt(Command):
@tool_required('img2txt')
......@@ -117,11 +121,13 @@ class JPEGImageFile(File):
def compare_details(self, other, source=None):
content_diff = Difference.from_command(Img2Txt, self.path, other.path,
source='Image content')
if content_diff is not None:
if (content_diff is not None) and Config().html_output:
try:
own_size = get_image_size(self.path)
other_size = get_image_size(other.path)
if own_size == other_size:
logger.debug('Generating visual difference for %s and %s',
self.path, other.path)
content_diff.add_visuals([
pixel_difference(self.path, other.path),
flicker_difference(self.path, other.path)
......@@ -152,11 +158,13 @@ class ICOImageFile(File):
else:
content_diff = Difference.from_command(Img2Txt, png_a, png_b,
source='Image content')
if content_diff is not None:
if (content_diff is not None) and Config().html_output:
try:
own_size = get_image_size(self.path)
other_size = get_image_size(other.path)
if own_size == other_size:
logger.debug('Generating visual difference for %s and %s',
self.path, other.path)
content_diff.add_visuals([
pixel_difference(self.path, other.path),
flicker_difference(self.path, other.path)
......
......@@ -19,12 +19,18 @@
import re
import functools
import subprocess
import logging
from diffoscope.tools import tool_required
from diffoscope.difference import Difference
from diffoscope.config import Config
from .utils.file import File
from .utils.command import Command
from .image import pixel_difference, flicker_difference, get_image_size
logger = logging.getLogger(__name__)
class Sng(Command):
......@@ -42,4 +48,20 @@ class PngFile(File):
RE_FILE_TYPE = re.compile(r'^PNG image data\b')
def compare_details(self, other, source=None):
return [Difference.from_command(Sng, self.path, other.path, source='sng')]
sng_diff = Difference.from_command(Sng, self.path, other.path, source='sng')
differences = [sng_diff]
if (sng_diff is not None) and Config().html_output:
try:
own_size = get_image_size(self.path)
other_size = get_image_size(other.path)
if own_size == other_size:
logger.debug('Generating visual difference for %s and %s',
self.path, other.path)
content_diff = Difference(None, self.path, other.path,
source='Image content')
content_diff.add_visuals([pixel_difference(self.path, other.path),
flicker_difference(self.path, other.path)])
differences.append(content_diff)
except subprocess.CalledProcessError: #noqa
pass
return differences
......@@ -34,6 +34,7 @@ class Config(object):
fuzzy_threshold = 60
enforce_constraints = True
excludes = ()
html_output = False
_singleton = {}
......
......@@ -285,6 +285,8 @@ def run_diffoscope(parsed_args):
Config().fuzzy_threshold = parsed_args.fuzzy_threshold
Config().new_file = parsed_args.new_file
Config().excludes = parsed_args.excludes
Config().html_output = any((parsed_args.html_output,
parsed_args.html_output_directory))
set_path()
set_locale()
logger.debug('Starting comparison')
......
......@@ -424,7 +424,7 @@ def output_unified_diff(print_func, css_url, directory, unified_diff, has_intern
print_func(templates.UD_TABLE_FOOTER % {"filename": html.escape("%s-1.html" % mainname), "text": text}, force=True)
def output_visual(print_func, visual, parents):
logger.debug('visual difference for %s', visual.source)
logger.debug('including image for %s', visual.source)
sources = parents + [visual.source]
print_func(u'<div class="difference">')
print_func(u'<div class="diffheader">')
......@@ -479,10 +479,10 @@ def output_difference(difference, print_func, css_url, directory, parents):
print_func(u'<div class="comment">%s</div>'
% u'<br />'.join(map(html.escape, difference.comments)))
print_func(u"</div>")
if difference.unified_diff and len(difference.visuals) > 0:
if len(difference.visuals) > 0:
for visual in difference.visuals:
output_visual(print_func, visual, sources)
elif difference.unified_diff:
if difference.unified_diff:
output_unified_diff(print_func, css_url, directory, difference.unified_diff, difference.has_internal_linenos)
for detail in difference.details:
output_difference(detail, print_func, css_url, directory, sources)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment