#изображения
На создание данного поста меня вдохновило это, это и это. Если эти rarjpeg'и можно создать, значит можно и определить их среди обычных "невинных" изображений. Под подозрение сразу попадают .jpg и .png. А как же отличить раржпег от обычной картинки? Банальное сравнение размера (если, например, картинка больше 10 Мб, то она может быть раржпегом) не поможет - могут быть разные размеры: картинка 10Кб с спрятанным в ней однострочным текстовиком или большая фотография с довольно большим аудиофайлом внутри. Как бы вы отличили? Я бы сделал так: расчитываем размер изображения (высота*ширина*глубина_цвета) и сравниваем его с настоящим размером файла. Не сошлось - значит раржпег. Но как же тогда расчитать размер EXIF и сжатие (у jpg), они же тоже часть изображения? UPDATE Написал рабочий (довольно шустрый) алгоритм на Java (проверял на Android'e). Спокойно работает с png+zip/rar, jpg+zip/rar. //Определим заголовки файлов String HEADER_RAR = "Rar!"; //Для .rar это будет Rar! String HEADER_ZIP = new String(new BigInteger("504B0304", 16).toByteArray()); //а для .zip будет "PK" и ещё два нечитаемых символа, поэтому мы получим их из HEX-кода //создаём массив строк с путями к нужным изображениям (ArrayListmImages) ArrayList mRarjpegs = new ArrayList (); //массив с путями к раржпегам for (String path : mImages) { //проверяем каждый файл try { BufferedReader br = new BufferedReader(new FileReader(path)); String line; while ((line = br.readLine()) != null) //открываем файл построчно... { if (line.contains(HEADER_RAR) || line.contains(HEADER_ZIP)) // ...если в строке нашёлся заголовок одного из архивов... { mRarjpegs.add(path); // ...то добавим его в список раржпегов break; // ...и выйдем из цикла, чтобы не считывать остальную часть файла } } } catch (Exception ex) { /* что-то своё */ } } //На выходе получим mRarjpegs, наполненный путями
Ответы
Ответ 1
Я когда-то писал для себя подобное. Вроде работает. enum RJClassification { NotJpeg, JustJpeg, JpegWithUnrecognizedTail, JpegWithRarTail } static class RJClassifier { public static RJClassification Classify(byte[] data, out long payloadIndex) { payloadIndex = 0; JpegParser jpp = new JpegParser(data, 0); if (!jpp.HasJpegHeader()) return RJClassification.NotJpeg; var jpegEnd = jpp.SkipJpegHeader(); if (!jpegEnd.HasValue) return RJClassification.NotJpeg; var rrp = new RarParser(data, jpegEnd.Value); var rarStart = rrp.FindRarHeader(); if (!rarStart.HasValue) return RJClassification.JpegWithUnrecognizedTail; payloadIndex = rarStart.Value; return RJClassification.JpegWithRarTail; } } class RarParser { byte[] data; long startIndex; public RarParser(byte[] data, long startIndex) { this.data = data; this.startIndex = startIndex; } byte[] signature = { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 }; public long? FindRarHeader() { // state machine int state = 0; for (long i = startIndex; i < data.LongLength; i++) { if (data[i] == signature[state]) { state++; if (state == signature.Length) return i + 1 - state; } else { if (state > 0) i--; // need to recheck the current byte state = 0; } } return null; } } JPEG parser чересчур длинный, положил сюда. Для других форматов картинок нужен, понятно, другой картиночный парсер. Или можно вообще без него, если скармливать RarParser'у ноль в качестве startIndex (но будет дольше и менее надёжно). Упс, кажется, код никогда не возвращает JustJpeg. Нужна ещё проверка после var jpegEnd = jpp.SkipJpegHeader();.
Комментариев нет:
Отправить комментарий