Иногда мне нужно написать больше документации, чем просто комментарии в коде. И иногда для этих объяснений нужны скриншоты. Иногда условия получения такого скриншота настолько странные, что я прошу разработчика сделать для меня скриншот. Иногда скриншот не соответствует моим характеристикам, и мне нужно изменить его размер, чтобы он выглядел красиво.
Как видите, обстоятельства для волшебного «Lossless Screenshot Resizer» крайне маловероятны. Во всяком случае, мне кажется, что мне это нужно каждый день. Но его пока нет.
Я видел, как вы здесь, на PCG, решали удивительные графические головоломки , так что я думаю, что это довольно скучно для вас ...
Спецификация
- Программа делает скриншот одного окна в качестве ввода
- На скриншоте не используются стеклянные эффекты или аналогичные элементы (поэтому вам не нужно разбираться с фоновыми материалами, которые просвечивают)
- Формат входного файла - PNG (или любой другой формат без потерь, чтобы вам не приходилось иметь дело с артефактами сжатия)
- Формат выходного файла такой же, как формат входного файла
- Программа создает скриншот разного размера в качестве вывода. Минимальное требование уменьшается в размере.
- Пользователь должен указать ожидаемый размер вывода. Если вы можете дать подсказки о минимальном размере, который ваша программа может создать из заданного ввода, это полезно.
- Выходной скриншот не должен содержать меньше информации, если интерпретируется человеком. Вы не должны удалять текстовое или графическое содержимое, но должны удалять только области с фоном. Смотрите примеры ниже.
- Если невозможно получить ожидаемый размер, программа должна указать это, а не просто вывести из строя или удалить информацию без дальнейшего уведомления.
- Если программа указывает области, которые будут удалены по причинам проверки, это должно увеличить ее популярность.
- Программа может нуждаться в некотором другом пользовательском вводе, например, чтобы определить начальную точку для оптимизации.
правила
Это конкурс популярности. Ответ с большинством голосов 2015-03-08 принимается.
Примеры
Скриншот Windows XP. Оригинальный размер: 1003х685 пикселей.
Примеры областей (красный: вертикальный, желтый: горизонтальный), которые можно удалить без потери какой-либо информации (текста или изображений). Обратите внимание, что красная полоса не является смежной. В этом примере не указаны все возможные пиксели, которые потенциально могут быть удалены.
Изменение без потерь: 783x424 пикселей.
Скриншот Windows 10. Оригинальный размер: 999x593 пикселей.
Примеры областей, которые можно удалить.
Снимок экрана без потерь: 689x320 пикселей.
Обратите внимание, что текст заголовка («Загрузки») и «Эта папка пуста» больше не центрируются. Конечно, было бы лучше, если бы оно было центрировано, и если ваше решение обеспечивает это, оно должно стать более популярным.
источник
Ответы:
питон
функция
delrows
удаляет все, кроме одной повторяющейся строки, и возвращает транспонированное изображение, применяя его дважды, также удаляя столбцы и транспонируя его обратно. Дополнительноthreshold
контролирует, сколько пикселей может различаться для двух линий, которые по-прежнему считаются одинаковыми.Переключение компаратора
mask
из в>
к<=
вместо будет выводить удаленные области, которые в основном пустое пространство.игра в гольф (потому что почему бы и нет)
Вместо того, чтобы сравнивать каждый пиксель, он смотрит только на сумму, в качестве побочного эффекта он также преобразует снимок экрана в оттенки серого и имеет проблемы с сохраняющими сумму перестановками, такими как стрелка вниз в адресной строке Win8. Скриншот
источник
Java: попробуйте без потерь и откат к содержанию
(Лучший результат без потерь!)
Когда я впервые посмотрел на этот вопрос, я подумал, что это не головоломка или вызов, а просто кто-то, отчаянно нуждающийся в программе и ее коде;) Но я в своей природе решаю проблемы со зрением, поэтому я не мог помешать себе попробовать эту задачу !
Я придумал следующий подход и комбинацию алгоритмов.
В псевдокоде это выглядит так:
Используемые методики:
Программа
Программа может обрезать скриншоты без потерь, но имеет возможность вернуться к контентной обрезке, которая не без потерь на 100%. Аргументы программы могут быть изменены для достижения лучших результатов.
Примечание: программа может быть улучшена многими способами (у меня не так много свободного времени!)
аргументы
Код
Полученные результаты
Скриншот XP без потерь без желаемого размера (максимальное сжатие без потерь)
Аргументы: "image.png" 1 1 5 10 false 0
Результат: 836 х 323
Скриншот XP до 800x600
Аргументы: "image.png" 800 600 6 10 true 60
Результат: 800 х 600
Алгоритм без потерь удаляет около 155 горизонтальных линий, а алгоритм возвращается к удалению с учетом содержимого, поэтому можно увидеть некоторые артефакты.
Скриншот Windows 10 до 700x300
Аргументы: "image.png" 700 300 6 10 true 60
Результат: 700 х 300
Алгоритм без потерь удаляет 270 горизонтальных линий, а алгоритм возвращается к удалению с учетом содержимого, которое удаляет еще 29. По вертикали используется только алгоритм без потерь.
Скриншот Windows 10 с учетом содержимого до 400x200 (тест)
Аргументы: "image.png" 400 200 5 10 true 600
Результат: 400 х 200
Это был тест, чтобы увидеть, как будет выглядеть полученное изображение после интенсивного использования контентно-зависимой функции. Результат сильно поврежден, но не узнаваем.
источник
C #, алгоритм, как я бы сделал это вручную
Это моя первая программа для обработки изображений, и мне потребовалось некоторое время, чтобы реализовать ее
LockBits
и т. Д. Но я хотел, чтобы она была быстрой (с использованиемParallel.For
), чтобы получить почти мгновенную обратную связь.В основном мой алгоритм основан на наблюдениях за тем, как я удаляю пиксели вручную из скриншота:
На данный момент я делаю это только по горизонтали. Вертикальный результат может использовать тот же алгоритм и работать с повернутым на 90 ° изображением, поэтому теоретически это возможно.
Полученные результаты
Это скриншот моего приложения с обнаруженными регионами:
И это результат для скриншота Windows 10 и порога 48 пикселей. Вывод составляет 681 пикселей в ширину. К сожалению, он не идеален (см. «Поиск загрузок» и некоторые вертикальные столбцы).
И еще один с порогом в 64 пикселя (шириной 567 пикселей). Это выглядит даже лучше.
Общий результат применения поворота для обрезки со всего дна (567x304 пикселей).
Для Windows XP мне нужно было немного изменить код, поскольку пиксели не совсем равны. Я применяю порог сходства 8 (разница в значении RGB). Обратите внимание на некоторые артефакты в столбцах.
Код
Ну, моя первая попытка обработки изображений. Выглядит не очень хорошо, правда? Здесь перечислены только основные алгоритмы, а не пользовательский интерфейс и не поворот на 90 °.
источник
Haskell, используя наивное удаление повторяющихся последовательных строк
К сожалению, этот модуль предоставляет только функцию с очень общим типом
Eq a => [[a]] -> [[a]]
, так как я не знаю, как редактировать файлы изображений в Haskell, однако я уверен, что можно преобразовать изображение PNG в[[Color]]
значение, и я думаю,instance Eq Color
что легко определимоРассматриваемая функция есть
resizeL
.Код:
Объяснение:
Примечание:
a : b
означает элемент сa
префиксом в списке типаa
, в результате чего список. Это фундаментальная конструкция списков.[]
обозначает пустой список.Примечание:
a :: b
средствоa
относится к типуb
. Например, еслиa :: k
, тогда(a : []) :: [k]
, где[x]
обозначает список, содержащий вещи типаx
.Это означает, что
(:)
само по себе, без каких-либо аргументов:: a -> [a] -> [a]
.->
Обозначает функцию от чего - то к чему - то.Он
import Data.List
просто получает какую-то работу, которую сделали для нас другие люди, и позволяет нам использовать их функции, не переписывая их.Сначала определите функцию
nubSequential :: Eq a => [a] -> [a]
.Эта функция удаляет последующие элементы списка, которые идентичны.
Так,
nubSequential [1, 2, 2, 3] === [1, 2, 3]
. Теперь мы будем сокращать эту функцию какnS
.Если
nS
применяется к пустому списку, ничего не поделаешь, и мы просто возвращаем пустой список.Если
nS
применяется к списку с содержимым, то может быть выполнена фактическая обработка. Для этого нам понадобится вторая функция, здесь вwhere
-clause, чтобы использовать рекурсию, поскольку нашаnS
не отслеживает элемент для сравнения.Мы называем эту функцию
g
. Он работает, сравнивая свой первый аргумент с заголовком списка, который ему дали, и отбрасывая голову, если они совпадают, и вызывая себя в хвосте со старым первым аргументом. Если они этого не делают, он добавляет голову к хвосту, пропущенную через себя с головой в качестве нового первого аргумента.Чтобы использовать
g
, мы даем ему голову аргументаnS
и хвост в качестве двух аргументов.nS
теперь имеет типEq a => [a] -> [a]
, беря список и возвращая список. Это требует, чтобы мы могли проверить равенство между элементами, как это делается в определении функции.Затем мы составляем функции
nS
иtranspose
используем(.)
оператор.Сочинение функции означает следующее:
(f . g) x = f (g (x))
.В нашем примере
transpose
поворачивает таблицу на 90 °,nS
удаляет все последовательные равные элементы списка, в этом случае другие списки (это и есть таблица),transpose
поворачивает ее обратно иnS
снова удаляет последовательные равные элементы. Это по существу удаляет последующие повторяющиеся строки столбцов.Это возможно, потому что, если
a
проверяется на равенства (instance Eq a
), то[a]
тоже.Короче:
instance Eq a => Eq [a]
источник