Pull to refresh

Comments 18

Нетипичные вещи всегда требовали больше чем обычно усилий. Оставим вопрос окупаемости этих усилий под эту платформу. Задачку уже решали в картографических приложениях. Я бы как ленивый программист смотрел в ту сторону.
Хорошо, картинку целиком мы в памяти больше не храним.

Но в блоке
        // ********************
        // TODO: Рисуем здесь
        // ********************
надо откуда-то брать данные.

Будем лазить за частью картинки по http при каждом свайпе? Или подразумевается, что постер предварительно целиком выкачивается на винт/sd-карту?
Причина очень простая — это не гайд по рисованию постеров :) Моей задачей было рассказать про VirtualSurfaceImageSource. Ведь рисование больших изображений — только частный случай области применения VirtualSurfaceImageSource.

С картинкой все очень просто — с помощью BitmapDecoder::GetPixelDataAsync() получаем нужный нам регион. Код вы можете посмотреть в примере.
В картографиских сервисах, апи как правило позволяет задать размер тайла и как правило, он меньше экрана в разы и уже в приложении рисуется нужная мозаика.
Я что-то подобное делал на XNA еще во времена WP7, делил большую карту на кусочки 160*160, при свайпе загружал нужные и выгружал устаревшие, работало шустро. Ну это, наверное, относиться к
1. Написать все самому

Не совсем понял, вы утверждаете, что вариант с XNA будет лучше?
Я привел свой опыт с использованием XNA, как менее производительный в сравнении с DirectX и на более слабом железе, на котором бегала WP71.
Суть не в этом, а в другом подходе, заключающимся в подготовке текстуры заранее – путем разрезав её на маленькие тайлы, в статье запрета на это нет. Логики при сдвиге конечно становиться больше, но результат в производительности очевидный, да потери качества не возникает.
Производительность данного способа абсолютно такая же. Лагает вовсе не из-за этого. Причина в том, что в моем примере нужный регион декодируется по требованию.

Суть не в этом, а в другом подходе, заключающимся в подготовке текстуры заранее – путем разрезав её на маленькие тайлы, в статье запрета на это нет.

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

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

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

при свайпе загружал нужные и выгружал устаревшие


P.S. Тайлы — небольшие изображения одинаковых размеров, которые и служат фрагментами большой картины. Таким образом можно строить огромные двухмерные пространства, расходующие совсем немного памяти.
Я долго и внимательно перечитывал ваш комментарий раз 20, перед тем как написать свой комментарий. Нет никакой разницы между хранением всей картинки и множества тайлов составляющих данную картинку.

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

Для постера такой вариант неприменим, по той причине, что в нем нет повторяющихся частей. Прочтите начало статьи еще раз, там подробно написано, что мы рисуем большую JPEG картинку, а не игровой мир.
И что что нету повторяющихся тайлов и это не игра? Зачем себя ограничивать?
Делим Вашу большую JPEG картинку на n маленьких равных частей допустим 160*160. Пусть наш экран 800*480. Те для отображения нужно 15 тайлов, чтобы их отобразить нужно поднять с диска 15 тайлов. Двигаем картинку вправо на 80 пикселей, нам необходимо загрузить еще 5 тайлов. Двигаем еще в право на 80, пикселей, теперь старые 5 тайлов не нужны – выгружаем их.
И того было два сдвига по 80 пикселей. Подгрузили 5 тайлов.
Ваш вариант, два декодирования из большого изображения, размером с экран.
Вы серьезно считаете, что декодирование из большого файла определенного куска памяти, равного площади всего экрана будет быстрее или равно чем подгрузить из памяти 5 заранее подготовленных маленьких файлов?
И что что нету повторяющихся тайлов и это не игра? Зачем себя ограничивать?

О каких ограничениях вы вообще говорите? У нас есть задача, её надо решить.
Делим Вашу большую JPEG картинку на n маленьких равных частей допустим 160*160. Пусть наш экран 800*480. Те для отображения нужно 15 тайлов, чтобы их отобразить нужно поднять с диска 15 тайлов.

Вы серьезно считаете, что декодирование из большого файла определенного куска памяти, равного площади всего экрана будет быстрее или равно чем подгрузить из памяти 5 заранее подготовленных маленьких файлов?

Т.е. вы предлагаете при запуске приложения декодировать целиком картинку и сохранить все 500 МБ на диск? Хуже не придумаешь…
А что мешает?
• Порезать её на компе и засунуть уже готовую в инстал пакет (если это приложение – один постер).
• Сервер отдает её частями (если она прилетает от сервера, по аналогии с картографическими сервисами).
• Да даже получить и порезать её – займет не так много времени!
Без обид, но вы сейчас какую-то глупость написали. Для чего все это?
А для чего вся Ваша статья написана, да еще и в хабе «Высокая производительность*» если конечный результат получился на 4 букву алфавита? Возможно дальше будет что-то стоящее!
Была задача отобразить картинку 9300 x 12300. Я предложил альтернативное решение которое работало для намного большего расширения и на более слабом железе. Возможно оно Вам не подходит, но оно попадает под основою задачу, озвученную Вами!
P.S.Не вижу смысла препираться, если что-то хотите обсудить – прошу в личку.
если конечный результат получился на 4 букву алфавита
Ну-ну, не разобравшись полезли на эмоциях ярлыки навешивать. Я вам объяснить пытаюсь, а вы в свое уперлись, лучше бы переспросили если не поняли.

Я предложил альтернативное решение которое работало для намного большего расширения и на более слабом железе.
Повторюсь еще раз — принципиально разбиение на «тайлы» ни чем не отличается от использования VSIS, по той причине, что VSIS собственно этим и занимается. Более того, VSIS будет уделывать «тайлы фиксированного размера» в производительности и потреблении памяти, хоть и немного.

Попробую объяснить еще раз: те самые лаги возникают вовсе не из-за VSIS. Если для данной задачи использовать ваше «решение», то ваши лаги ничем не будут отличаться от «наших».

А теперь обсудим ваши предложения. Я имею в виду это:
А что мешает?
• Порезать её на компе и засунуть уже готовую в инстал пакет (если это приложение – один постер).
• Сервер отдает её частями (если она прилетает от сервера, по аналогии с картографическими сервисами).
• Да даже получить и порезать её – займет не так много времени!

Для примера наша выдуманная задача останется той же самой — отобразить постер с кинопоиска.
1 вариант отпадает, объяснять почему надеюсь не придется.
2 вариант отпадает, никто в кинопоиске и пальцем не шевельнется. Это не карты, еще раз повторяю.
3 вариант отпадает, из комментария выше надеюсь будет понятно почему.
Пусть даже вы и добились своего и предварительно разрезали на тайлы. Но будет ли выигрыш в производительности? Уж точно не будет, для пользователей классических жестких дисков, с огромным временем случайного доступа, все станет только хуже.

Ну а теперь к самому главному — карты, раз уж затронули картографические сервисы. Растровые карты — прошлый век. Если сможете отобразить векторные карты силами XNA в придачу с отзывчивым зумом, отлично, лично вручу в руки медаль! Не спорю, это может и возможно, но я скорее повешусь. А вот за VSIS и Direct2D я бы вам вряд ли вручил.
Аналогичная ситуация с браузерами или Word с Excel, которые я упомянул в своей статье.

Комментарий получился объёмным, но я постарался еще раз пройтись по всем возникшим у вас вопросам. Надеюсь больше возражений у вас не будет, если есть что обсудить, пожалуйста в ЛС. А данный комментарий пусть будет всем на обозрение, раз уж мы обсудили все преимущества и недостатки обоих подходов.
Думаю, вы просто не поняли, что вам пытается сказать dampirik
Картинка не будет весить 500 мегабайт, так как это всего лишь её декодированное представление в формате RGBA, т.е. на один пиксель 4 байта. Фактический ее размер в фотмате jpeg будет около нескольких мегабайт.
Путь решения броблемы — загрузить картинку и разбить на тайлы, т.е. по факту картинка станет сеткой (произвольного размера, пусть 256х256 пикселей).
Почему ваш способ плох — для картинки формата jpeg, когда вы запросите определенный ее участок, то ВСЯ картинка дешифруется.
Логика сводится к простому — LoadTilesInsideScreen + UnloadTilesOutsideScreen.
для простоты имена тайлов такие — «poster_cell_X_cell_Y.jpg»
В итоге всё будет производительно и без лагов, так же работает google_maps.
Про фразу «Растровые карты — прошлый век»: Я не очень представляю, как хранить это в векторе LINK
Так же, если больших картинок много, можно хранить нарезку на сервере и подгружать их в нескольких потоках. Получится TMS-сервис :)

И так же иногда возникает потребность не в JPEG изображениях, а PNG — в виду прозрачности и возможности наложения. Имею ввиду, что в задаче с наложением картинок без сетки не обойтись.

Была задача положить на карту — JPEG изображение размером с 500 метров. Проблема была в том что картинку приходила от пользователя, и нельзя было ее подготовить заранее. Пришлось использовать похожий способ, при помощи GDI+ и MsImg. Затея оказалась неудачной — так как GDI+ умеет работать только в основном потоке. И пользователю приходилось ждать (пусть не долго).

То есть у тайловой сетки простое преимущество — кеширование результата.
UFO just landed and posted this here
Sign up to leave a comment.

Articles