vitus_wagner (
vitus_wagner) wrote2009-09-28 02:58 pm
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Entry tags:
Вьюеры картинок
Почему-то среди широко известных опенсурсных программ нет программы, которая бы позволяла просматривать БОЛЬШИЕ картинки. Под "большой картинкой" здесь понимается растровое изображение таких размеров, что его неупакованное RGB-представление (обычно получается по 32 бита на пиксел, но достаточно и 24) не лезет в оперативную память.
То есть в resource-constrained environments вроде maemo "большой картинкой" будет уже лист А4, отсканированный на 600dpi. На десктопе с гигабайтом жизнь попроще. Но все равно есть вполне полезные вещи вроде graphviz, которые могут сгенерировать картинку, которая будет большой и для десктопа.
Задача, казалось бы элементарно простая - читаем картинку последовательно, пересчитываем координаты пикселов с учетом текущего размера окна, масштаба и выбранного viewport и заполняем offscreen pixmap размером с экран. На неё-то места хватит практически всегда. Это в DOS real mode на копию VESA-шного фреймбуфера в памяти места не хватало. И то вьюеры картинок под DOS писали и они работали.
Оказывается проблема в том, что у современного программиста даже не возникает мысль подойти к задаче системно. Вместо этого ищется готовый инструмент. На освоение которого уходит больше времени и сил, чем на написание вышеописанного простого алгоритма с нуля. Причем, желательно инструмент поуниверсальнее. Берем какой-нибудь GEGL и обнаруживаем что ему для загрузки картинки в свой tiled формат требуется больше места, чем у нас имеется в том, что на нашем девайсе заменяет жесткий диск.
То есть в resource-constrained environments вроде maemo "большой картинкой" будет уже лист А4, отсканированный на 600dpi. На десктопе с гигабайтом жизнь попроще. Но все равно есть вполне полезные вещи вроде graphviz, которые могут сгенерировать картинку, которая будет большой и для десктопа.
Задача, казалось бы элементарно простая - читаем картинку последовательно, пересчитываем координаты пикселов с учетом текущего размера окна, масштаба и выбранного viewport и заполняем offscreen pixmap размером с экран. На неё-то места хватит практически всегда. Это в DOS real mode на копию VESA-шного фреймбуфера в памяти места не хватало. И то вьюеры картинок под DOS писали и они работали.
Оказывается проблема в том, что у современного программиста даже не возникает мысль подойти к задаче системно. Вместо этого ищется готовый инструмент. На освоение которого уходит больше времени и сил, чем на написание вышеописанного простого алгоритма с нуля. Причем, желательно инструмент поуниверсальнее. Берем какой-нибудь GEGL и обнаруживаем что ему для загрузки картинки в свой tiled формат требуется больше места, чем у нас имеется в том, что на нашем девайсе заменяет жесткий диск.
no subject
Кэширование файловых смещений не поможет -- нужно хранить еще и внутреннее состояние распаковщика (причем смещения хранить с учетом номера бита, а не только байта).
Так что я в данном случае конвертил бы в tiled формат (например TIFF или свою надстройку над набором тайлов-как-JPEG/png сложенных в один контейнер с заголовком).
В случае тайлов разумного размера каждый из них можно грузить в память целиком, отображение тривиально.
Написание конвертера тоже не представляет особой трудности.
Или нужны шашечки ("просмотр _произвольной_ огромной картинки _стандартного_ формата со скроллом и зумом") а не просто возможность работы с огромными изображениями?
В самом тупом случае можно резать огромное изображение на кучу мелких, на старте проходя страйпами, а потом реализовать отображение получившихся тайлов.
Впоследствии можно в случае jpeg блоки 8*8 целиком пробрасывать, чтобы не тратить время на перекодировку.
И только если можно забить на все кроме jpeg -- только тогда я бы стал привязываться к внутренней структуре данных.
no subject
Конечно, у меня был опыт работы с большими растрами путем загрузки правильно упакованного формата в память. И влезало. На 286 процессоре, где все адресное пространство 24Мб. Растр был 25000x15000.
Кстати, использвоалась построчная упаковка, а не tiled. Потому что tiled гораздо сложнее, а реальных преимуществ на данной задаче не дает.
Но в операционных системах с современными сисемами кэширования это нафиг не нужно. Проще перечитать. Следует учитывать, что процессор у нас обычно существенно обгоняет по скорости прочие подсистемы, и экономить его за счет усложнения системы имеет смысл только если тупое лобовое решение окажется неприемлемым по скорости.
Вот над кэшированием состояния распаковщика стоит подумать. Правда, очевидно, что кэшировать его для КАЖДОЙ строки растра - бессмыслено. Возможно, стоит для каждой сотой или даже каждой тысячной.
no subject
кстати, "несколько мегабайт" -- излишне оптимистично.
Приходят тут репорты от юзеров "я уменьшил картинку до 200 MB но все равно обработка идет медленно..."
no subject
premature optimization is the root of all evil.
И что-то мне подсказывает, что заявленная картинка на 200Мб была ни разу не в png.
no subject
Спрашивали его о размере в пикселях, отвечает в мегабайтах неизвестного формата...
"Смириться с тормозами" -- это выход.
Но если вариант требующий написания большего куска кода в 99% случаев не имеет преимуществ, то скорее всего он будет отклонен.
Пока 99% входят в память, никто не будет даже думать о чтении картинки по частям.
Пока нам хватало 2 ГБ адресного пространства, я не парился с собственным свопом, полагаясь на системный. Но пришлось :)