vitus_wagner: My photo 2005 (Default)
vitus_wagner ([personal profile] vitus_wagner) wrote2009-09-28 02:58 pm

Вьюеры картинок

Почему-то среди широко известных опенсурсных программ нет программы, которая бы позволяла просматривать БОЛЬШИЕ картинки. Под "большой картинкой" здесь понимается растровое изображение таких размеров, что его неупакованное RGB-представление (обычно получается по 32 бита на пиксел, но достаточно и 24) не лезет в оперативную память.

То есть в resource-constrained environments вроде maemo "большой картинкой" будет уже лист А4, отсканированный на 600dpi. На десктопе с гигабайтом жизнь попроще. Но все равно есть вполне полезные вещи вроде graphviz, которые могут сгенерировать картинку, которая будет большой и для десктопа.

Задача, казалось бы элементарно простая - читаем картинку последовательно, пересчитываем координаты пикселов с учетом текущего размера окна, масштаба и выбранного viewport и заполняем offscreen pixmap размером с экран. На неё-то места хватит практически всегда. Это в DOS real mode на копию VESA-шного фреймбуфера в памяти места не хватало. И то вьюеры картинок под DOS писали и они работали.

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

[identity profile] kh13.livejournal.com 2009-09-30 07:50 am (UTC)(link)
Проблема в том что найти нужную скан-строку в файле мы можем только распаковывая весь поток с самого начала.
Кэширование файловых смещений не поможет -- нужно хранить еще и внутреннее состояние распаковщика (причем смещения хранить с учетом номера бита, а не только байта).

Так что я в данном случае конвертил бы в tiled формат (например TIFF или свою надстройку над набором тайлов-как-JPEG/png сложенных в один контейнер с заголовком).

В случае тайлов разумного размера каждый из них можно грузить в память целиком, отображение тривиально.
Написание конвертера тоже не представляет особой трудности.

Или нужны шашечки ("просмотр _произвольной_ огромной картинки _стандартного_ формата со скроллом и зумом") а не просто возможность работы с огромными изображениями?

В самом тупом случае можно резать огромное изображение на кучу мелких, на старте проходя страйпами, а потом реализовать отображение получившихся тайлов.

Впоследствии можно в случае jpeg блоки 8*8 целиком пробрасывать, чтобы не тратить время на перекодировку.

И только если можно забить на все кроме jpeg -- только тогда я бы стал привязываться к внутренней структуре данных.

[identity profile] kh13.livejournal.com 2009-09-30 09:27 am (UTC)(link)
собственно варианта два: или требовать на входе "правильный" формат (свой или не свой -- неважно) или смириться с тормозами при скролле/зуме.

кстати, "несколько мегабайт" -- излишне оптимистично.

Приходят тут репорты от юзеров "я уменьшил картинку до 200 MB но все равно обработка идет медленно..."

[identity profile] kh13.livejournal.com 2009-09-30 10:39 am (UTC)(link)
от юзеров часто очень сложно добиться конкретики.
Спрашивали его о размере в пикселях, отвечает в мегабайтах неизвестного формата...

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

Пока нам хватало 2 ГБ адресного пространства, я не парился с собственным свопом, полагаясь на системный. Но пришлось :)