A home for my visual webpage diffing technology.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
5.2 KiB

  1. #!/usr/bin/env bash
  2. loc_storage="${HOME}/.config/url-diff";
  3. if [[ ! -z "${URLDIFF_STORAGE_DIR}" ]]; then loc_storage="${URLDIFF_STORAGE_DIR}"; fi
  4. loc_firefox_profile="${loc_storage}/firefox-profile";
  5. loc_prev_images="${loc_storage}/previous-images";
  6. highlight_colour="${URLDIFF_HIGHLIGHT_COLOUR:-#ff000044}";
  7. quiet="${URLDIFF_QUIET:-false}";
  8. window_width="${URLDIFF_WINDOW_WIDTH}";
  9. change_threshold="${URLDIFF_CHANGE_THRESHOLD:-2}";
  10. ###############################################################################
  11. if [[ -z "$(type -p calc)" ]]; then
  12. echo "calc command not detected - it would appear it is not installed" >&2;
  13. echo "Install it like this on debian systems:" >&2;
  14. echo " sudo apt install apcalc" >&2;
  15. fi
  16. ###############################################################################
  17. log_msg() {
  18. if [[ "${quiet}" == "true" ]]; then
  19. return 0;
  20. fi
  21. echo "[${SECONDS}] $*";
  22. }
  23. # $1 Image to process
  24. # $2 Colour to find
  25. calculate_percentage_colour() {
  26. loc_image="${1}";
  27. colour="${2}";
  28. if [[ -z "${colour}" ]]; then
  29. log_msg "calculate_percentage_colour/Error: No colour specified." >&2;
  30. return 1;
  31. fi
  32. image_width="$(identify -format "%[fx:w]" "${loc_image}" )";
  33. image_height="$(identify -format "%[fx:h]" "${loc_image}")";
  34. pixel_count_colour="$(convert "${loc_image}" -fill black +opaque "${colour}" -fill white -opaque "${colour}" -format "%[fx:w*h*mean]" info:)";
  35. # echo "image_width: ${image_width}, image_height: ${image_height}, pixel_count_colour: ${pixel_count_colour}" >&2;
  36. calc -p "(${pixel_count_colour} / (${image_width}*${image_height})) * 100" | tr -d '~';
  37. }
  38. ###############################################################################
  39. mode="${1}";
  40. shift;
  41. if [[ -z "${mode}" ]]; then
  42. echo -e "Webpage visual diff checker
  43. By Starbeamrainbowlabs
  44. Usage:
  45. webpage-diff {subcommand} [{arguments}]
  46. Subcommands:
  47. check {url} {output_diff_image} [{output_apng}]
  48. Checks the given URL for differences, and saves a diff
  49. image to a specified location. Exits with code 0 if
  50. differences are found, or code 1 if no differences are
  51. found.
  52. Optionally generates an animated PNG that alternates
  53. between the 2 screenshots.
  54. Environment Variables:
  55. Variable Default variable
  56. ----------------------------------------------------------------------
  57. URLDIFF_STORAGE_DIR ~/.config/url-diff
  58. The directory in which previous images are stored to diff
  59. against. The firefox profile is also stored in here.
  60. URLDIFF_HIGHLIGHT_COLOUR #ffffffcc
  61. The colour to highlight any changes in.
  62. URLDIFF_WINDOW_WIDTH
  63. The window width to tell firefox to screenshot with.
  64. URLDIFF_CHANGE_THRESHOLD 2
  65. The percentage of the screenshot that should have
  66. changed for it to count.
  67. Allows for ignoring random minor rendering artifacts.
  68. " >&2;
  69. fi
  70. # Create the config directories
  71. mkdir -p "${loc_firefox_profile}";
  72. mkdir -p "${loc_prev_images}";
  73. case "${mode}" in
  74. check )
  75. url="${1}";
  76. url_hash="$(echo "${url}" | sha256sum | cut -d ' ' -f 1)";
  77. loc_output_diffimage="${2}";
  78. loc_output_apng="${3}";
  79. tmpdir="$(mktemp -d)";
  80. on_exit() {
  81. rm -rf "${tmpdir}";
  82. }
  83. trap on_exit EXIT;
  84. loc_img_old="${loc_prev_images}/${url_hash}.png";
  85. loc_img_new="${tmpdir}/new.png";
  86. if [[ ! -d "$(dirname "${loc_output_diffimage}")" ]]; then
  87. echo "Error: Output directory for diff image does not exist";
  88. exit 2;
  89. fi
  90. log_msg "Taking screenshot";
  91. log_msg "$(firefox --window-size "${window_width}" --profile "${loc_firefox_profile}" --headless --screenshot "${loc_img_new}" "${url}" 2>&1)";
  92. if [[ ! -f "${loc_img_old}" ]]; then
  93. log_msg "No image exists yet, storing initial snapshot";
  94. mv "${loc_img_new}" "${loc_img_old}";
  95. exit 1;
  96. fi
  97. # eog "${loc_img_old}";
  98. # eog "${loc_img_new}";
  99. # img_hash_old="$(identify -quiet -format "%#" "${loc_img_old}")";
  100. # img_hash_new="$(identify -quiet -format "%#" "${loc_img_new}")";
  101. # Generate the diff image
  102. compare "${loc_img_old}" "${loc_img_new}" -compose src -highlight-color "${highlight_colour}" "${tmpdir}/diff.png";
  103. convert "${tmpdir}/diff.png" -transparent "#ffffffcc" "${tmpdir}/transp.png";
  104. # Work out how much of the image has changed
  105. percentage_changed="$(calculate_percentage_colour "${tmpdir}/transp.png" "${highlight_colour}")";
  106. if [[ -z "${percentage_changed}" ]]; then
  107. echo "Something went wrong when calculating the percentage changed - no value was returned";
  108. exit 1;
  109. fi
  110. log_msg "Changed: ${percentage_changed}%";
  111. # if [[ "${img_hash_new}" == "${img_hash_old}" ]]; then
  112. if [[ "$(calc -p "${percentage_changed} > ${change_threshold}")" -eq 0 ]]; then
  113. log_msg "No changes detected.";
  114. exit 1;
  115. fi
  116. log_msg "Changes detected, outputting diff image.";
  117. convert "${loc_img_new}" "${tmpdir}/transp.png" -compose over -composite "${loc_output_diffimage}";
  118. if which optipng >/dev/null 2>&1; then
  119. log_msg "Optimising new image";
  120. optipng "${loc_img_new}";
  121. fi
  122. if [[ ! -z "${loc_output_apng}" ]]; then
  123. log_msg "Making animated PNG";
  124. cp "${loc_img_old}" "${tmpdir}/0.png";
  125. cp "${loc_img_new}" "${tmpdir}/1.png";
  126. ffmpeg -hide_banner -r 1 -i "${tmpdir}/%d.png" -plays 0 "${loc_output_apng}";
  127. fi
  128. mv "${loc_img_new}" "${loc_img_old}";
  129. exit 0;
  130. ;;
  131. esac