суббота, 24 октября 2020 г.

Битые картинки и как их выявить


 Битые картинки в галерее с фотоаппаратов, камер, телефонов и прочих средств... Наверное это знакомо каждому. И большинство из нас не знает масштаба трагедии, пока не наткнётся на парочку таких замечательных картинок, наподобие той, что я прикрепил в шапке. К слову эту картинку я специально попортил, открыв в текстовом редакторе и добавив один символ в середину файла. Понятно, что исправить такой байт - проблема та ещё, т.к. требует глубокого семантического анализа и не всегда восстановление возможно. Однако, подобных проблем можно избежать путём резервного копирования и использования файловых систем, поддерживающих "лечение" поломанных байтов данных. Но, начнём с простого - как определить, какие файлы поломаны, чтобы восстановить их из резервной копии.

Итак, озадачившись вопросом поиска файлов, которые по тем или иным причинам повредились, я создал небольшой скрипт, который позволяет выявить перечень этих файлов в удобном виде.

Для этих целей я воспользовался возможностями библиотеки imagemagick, которая является главной зависимостью моего скрипта. Среди утилит, входящих в Imagemagick, есть утилита identify-im6 которая в обычной жизни используется для чтения информации из файлов изображений. Однако, побочным выводом этой команды, является определение повреждений в файлах. В частности, в выводе команды

$identify-im6 -regard-warnings -verbose image.jpg

 в случае наличия повреждений, проявляется строки вида:

identify-im6.q16: Corrupt JPEG data: premature end of data segment `image.jpg'

с перечислением проблем. Собственно это я и решил отловить.

Получился вот такой скриптик, который можно взять и пользоваться:

 #! /bin/bash
#Ask for path
helpFunction()
{
    echo ""
    echo "Использование: $0 -p 'директория для проверки' -o 'файл отчёта' "
    echo -e "\t-p Путь к проверяемым файлам"
    echo -e "\t-o Путь к файлу отч
ёту"
    exit 1
}
while getopts "p:o:"  opt
do
    case "$opt" in
    p ) folderToCheck="$OPTARG";;
    o ) outputFile="$OPTARG";;
    ? ) helpFunction ;;
    esac
done
if [ -z "$folderToCheck" ] || [ -z "$outputFile"]
then
    echo "Введите путь к директории для проверки и файл отчёта"
    helpFunction
fi

echo "Проверяем файлы изображения с помощью ImageMagick в $folderToCheck"
counter=1
Red="\033[0;31m"    # красный
Green="\033[0;32m"  # зелёный
Color_Off="\033[0m" # сброс текста

cd "${folderToCheck}"
# Перечисление файлов
count=$(find "$(pwd)" -type f -iname "*.jpg" -o -iname "*.jpeg" | wc -l | xargs) 
# Поиск всех файлов и обработка
find "$(pwd)" -type f -iname "*.jpg" -o -iname "*.jpeg" | while read -r line ; do
    result=$(identify-im6 -regard-warnings -verbose "${line}" > /dev/null 2>&1&&echo $?)
    if [[ "$result" == *"0"* ]] ; then
        echo -e "OK $line" >> /dev/null
        status="${Green}"
    else
        echo -e "БИТЫЙ ФАЙЛ $line" >> $outputFile
        status="${Red}"
    fi
    echo -e "${status} Файл ${counter} из ${count}${Color_Off} → ${line##*/}"
    counter=$(( $counter + 1 ))
done
echo "Запись файла ${outputFile}"
echo "-------------- ГОТОВО --------------"

 Это можно скопировать в файл вида find-crptd-img.sh, добавив возможность исполнения командой $chmod +x find-crptd-img.sh. После этого пользоваться скриптом можно будет с помощью команды:

$find-crptd-img.sh -p 'путь к папке с картинками' -o отчёт.txt 

 После чего скрипт пройдёт в директорию и начнёт читать подряд все файлы изображений формата JPEG (возможно в будущем я проапгрэйжу скрипт до проверки и других форматов, но пока так) и записывать в файл "отчёт.txt" битые файлы из директории.

Смею заметить, что у этого скрипта есть пара косяков - один из них это то, что в битые файлы запишутся модифицированные с помощью некоторых программ изображения, которые некорректно записали данные в файл. В частности это касается сшитых вручную панорам. Ну и вторая - то, что степень битости файлов никак не определена - возможно это коснулось только атрибутивной части и само изображение выглядит нормально. Тут уж просто стоит взглянуть на эти файлы своими глазами прежде, чем их удалять. 

В общем, как-то так, удачного использования.

Комментариев нет:

Отправить комментарий