пятница, 18 декабря 2015 г.

Конвертирование сферической панорамы в кубическую

Преамбула:

Как известно Adobe Flash Player, скажем так, подвергается гонениям со стороны браузеров всех мастей.

Один клиент имеет на сайте некоторое количество флеша как в виде простых анимашек, так и одну с панорама-вьювером с некоторым функционалом.

Если простые анимашки перевести на рельсы HTML5 достаточно просто, то с панорамой немного посложнее.

Выбор вьювера для панорамы пал на Pannellum.

Основные преимущества:

  • Опенсёрсный;
  • Шустрый;
  • Имеет кроме просмотра доп. возможности по размещению меток (метки отображаются в DOM, а не на canvas);
  • Имеет богатый набор опций для конфигурирования.



Проблема:

Pannellum отображает кубические панорамы, а у клиента сферическая. Встала проблема конвертации панорамы из сферической в кубическую.

В ходе поиска попадались как платные так и бесплатные утилиты. Но одни требовали "много денег", другие установку доп. софта. И вот чудом-юдом попалась одна подходящая опенсёрсная, без регистрации и смс установки стороннего софта и что тоже не маловажно кроссплатформенная.



Решение:
  1. Проверяем есть ли на компе java. Если нет, то качаем/устанавливаем (достаточно JRE).
  2. Качаем/распаковываем архив с утилитой от сюда или от сюда.
    Из всего архива нужен по сути только файл EquirectangularToCubic.jar
  3. Запускаем утилиту:

    java -jar EquirectangularToCubic.jar path_to_image.jpg
    

    Для примера можно взять эту сферическую панораму.


    На выходе получаем папку:
    cubic_path_to_image
        |__examplepano_b.jpg
        |__examplepano_d.jpg
        |__examplepano_f.jpg
        |__examplepano_l.jpg
        |__examplepano_r.jpg
        |__examplepano_u.jpg
    

Примечания:

  • Дополнительные ключи для запуска утилиты можно подсмотреть в файле EquirectangularToCubic.java в методе parseCommandLine
  • Важно! Для корректного отображения панорамы в Pannellum-е необходимо сделать переименование файлов:
    *_b.jpg ↔ *_f.jpg
    *_u.jpg ↔ *_r.jpg

пятница, 17 июля 2015 г.

Переход на страницу профиля пользователя Facebook по его ид

понедельник, 5 ноября 2012 г.

Антикэш на хэшах ресурсов: Вступление

Преамбула:
  • Есть некое приложение, которое в ходе своей работы использует множество внешних ресурсов/файлов;
  • Приложение работает в среде интернет-браузера;
  • Всего внешних ресурсов/файлов более 3000 единиц;
  • От релиза к релизу часть этих ресурсов может изменятся (например, художник перерисовал изображения некоторых айтемов или фоновых изображений, добавлены новые строковые, нормализованы по уровню громкости фоновые звуки, и прочее).

Итоговый алгоритм определения "протухшего" ресурса в кэше браузера определяется связкой "интернет-браузер + файловый сервер".
Подробнее о кэшировании можно почитать тут или воспользоватся результатами поиска.

Данная тема затронута в докладе на встрече RAFPUG, прошедшей в мае этого года в г.Челябинске (см. презентацию).

Проблема:
Алгоритм определения факта "протухания" файла в кэше браузера напрямую зависит от самого браузера и настроек отдающего файлового сервера.

Для уверенности в том, что клиентское приложение загрузит последнюю версию ресурса, необходимо принудительно сбросить кэш для всех ресурсов.
Сброс кэша осуществлялся добавлением в конец URL ресурса случайного параметра, например:
http://mysite.ru/images/bg.png?<random string>
Зачастую в качестве рандомного параметра используется номер версии приложения.

При выходе нового релиза возникнут следующие проблемы:
  • клиентское приложение заново грузит ресурсы, не взирая на то, что они не "протухли" в кэше браузера и остались неизменными с момента предыдущего релиза;
  • появится лишняя нагрузка на отдающий файловый сервер.

Следовательно, требуется добиться следующих результатов:
  1. Уверенность в том, что клиентское приложение будет использовать последнюю версию ресурса;
  2. Независимость от алгоритма поиска ресурса в кэше браузера;
  3. Снижение нагрузки на отдающий файловый сервер.

Решение:
Способ №1:
  1. Сформировать словарь соответствий относительных URL файлов с их хэшами, например: файлу
    ./images/bg.png
    соответствует хэш
    bb74f737c85c996cc2ec29c63698bf80
  2. Использовать в качестве антикэш-параметра значение хэша из словаря при формировании URL для загрузки файла, например:
    http://mysite.ru/images/bg.png?bb74f737c85c996cc2ec29c63698bf80
    Если соответствия не найдено — использовать строку с номером последней версии приложения.

Способ №2:
Данный способ был подсказан Михаилом Антипиным (Nox Noctis), за что ему огромное чистосердечное спасибо.
  1. Сформировать словарь соответствий оригинальных имен файлов с их новыми именами, например: оригинальному имени файла
    bg.png
    соответствует новое имя
    00240736ec53d1f23366122e8d12db5f9f06f7c70404000304d8c000
    В новое имя файла может быть "зашит" не только его хэш, но и дополнительные данные, например: размер файла в байтах, тип (png, jpg, ...), дату последнего изменения и прочее.
  2. Переименовать файлы в соответствии со словарем и переместить в общую для внешних ресурсов папку, например:
    http://mysite.ru/files/
  3. Определять его новое имя файла при формировании URL, по оригинальному имени используя словарь, например:
    http://mysite.ru/files/00240736ec53d1f23366122e8d12db5f9f06f7c70404000304d8c000

P.S.: Оба решения успешно протеситрованны и используются в боевых условиях.
В дальнейшем в данном посте будут размещены ссылки на описания реализаций каждого способа, а так же рассмотрены преимущества и недостатки каждого из них.

вторник, 30 октября 2012 г.

navigateToURL в цикле (Action Script)

Преамбула:
Возникла необходимость последовательно открывать в браузере несколько ссылок на ресурсы.

Проблема:
При последовательном или в цикле вызове функции navigateToURL отрабатывает всего лишь один вызов.

Решение:
  1. Приложение работает в standalone flashplayer-е или в среде flash-плагина браузера:
    const URLS:Array = ["http://ya.ru", "http://r0.ru"];
    stage.addEventListener(Event.ENTER_FRAME, function (e:Event):void {
        navigateToURL(new URLRequest(URLS.shift()), "_blank");
        if (URLS.length == 0) {
            e.target.removeEventListener(e.type, arguments.callee);
        }
    });
    
    Прим.: В качестве источника события Event.ENTER_FRAME можно использовать любой экземпляр класса Sprite или его наследников в независимости добавлен ли этот экземпляр в список отображения или нет.
  2. Приложение работает в среде flash-плагина браузера, доступен и разрешен вызов javascript-методов, то можно обойтись без подписки на событие Event.ENTER_FRAME:
    const URLS:Array = ["http://ya.ru", "http://r0.ru"];
    if (ExternalInterface.available) {
        for each (var url:String in URLS) {
            ExternalInterface.call("window.open", url);
        }
    }
    

пятница, 26 октября 2012 г.

As3/Flex offline-документация на русском (Action Script, Flex)

Преамбула:
Взбрендило мне заиметь документацию по as3 оффлайн - на тот случай когда интернета нет, а очень надо.

Проблема:
Поверхностный поиск в google не дал приемлемых результатов: ни по русской, ни по английской версии нет удобоваримой документации по классам as3, которую можно качнуть архивом.

Решение:
Нашлась программка Doc, написанная на AIR-е, в которой можно добавить путь до "книги" (в моем случае он http://help.adobe.com/ru_RU/FlashPlatform/reference/actionscript/3/). Затем она очень долго её выкачивала (~800 MB), индексировала и писала все это в локальную SQLite-базу.

К слову сказать, мне эта прога не понравилась: неудобно - внутристраничные ссылки не обрабатываются, т.е. при клике на метод или поле перехода в нужное место на странице не происходит.

НО! Главное, что эта программка скачала требуемую документацию пригодную для offline-использования. Спасибо ей за это. Забираем скачанное, анинсталим программку, пользуемся докой.

На случай ядерной войны выложил плотно упакованный 7-zip-ом архив с документацией:
Версия документации по состоянию на октябрь 2012.
As3DocumentatonOffline.7z (~11 MB, MD5: 891d9c8d6d4ba211fbd9087a2adf8f4e)

среда, 24 октября 2012 г.

Доступ к ресурсам защищенным Basic authentication (ActionScript, Basic Authorization)

Преамбула:
При разработке десктопного приложения на AIR столкнулся с проблемой доступа к ресурсам защищеным Basic access authentication или по-простому базовой авторизацией. Причем ресурсы расположены на разных серверах, условно site1.ru и site2.ru.
  • site1.ru – серверная часть приложения
  • site2.ru – хранилище статических ресурсов (картинки, флешки и прочая мультимедия)
При работе аналогичного приложения в среде flash-плагина браузера проблем нет, прошел авторизацию на каждом сервере один раз за сеанс работы браузера и шпарь себе дальше.

Проблема:
Для базовой авторизации необходимо в HTTP-запросе передавать заголовок Authorization с данными по логину и паролю.
Добавить нужный заголовок в URLRequest не представляется возможным из-за ограничений URLRequestHeader.
Нельзя, а хочется, воспользоватся такими средствами как загрузчик LoaderMax.

Решение:
Способ №1
Есть отличная библиотека as3httpclient с реализацией на сокетах аналога URLLoader-а и URLRequest-а которые позволяют добавить необходимые заголовки в HTTP-запрос.
var loader:SocketURLLoader = new SocketURLLoader();
loader.addEventListener(Event.COMPLETE, onComplete);

var request:SocketHTTPRequest = new SocketHTTPRequest();
request.url = "http://site1.ru";
request.requestHeaders = [new URLRequestHeader("Authorization", "Basic dXNlcjpwYXNzd29yZA==")];
loader.load(request);
dXNlcjpwYXNzd29yZA== 
это сериализованная в base64 строка "user:password".
Этот способ хорош для выполнения запросов обращеных к серверу бизнес-логики приложения и не удобен для загрузки статических ресурсов (в частости изображений) которые придется грузить в бинарном виде, заталкивать их в экземпляр класса Loader или другой класс для использования загруженного ресурса.

Способ №2
Как оказалось все уже придумано самими адобами.
Надо по-внимательней смотреть в документацию!
Встречайте URLRequestDefaults.
Достаточно один раз указать данные для авторизации, скажем в конструкторе главного класса приложения:
URLRequestDefaults.setLoginCredentialsForHost("site1.ru", "user", "password");
URLRequestDefaults.setLoginCredentialsForHost("site2.ru", "user", "password");
URLRequestDefaults.authenticate = true;

вторник, 22 мая 2012 г.

RAFPUG в Челябинске (19.05.2012)

Двинул речь вот тут про это.

Особое спасибо Михаилу Антипину (техническому директору mimimigames.ru ) за помощь по теме антикеша на хешах ресурсов.

P.S.: Спасибо тем, кто прослушал мою "тираду". Объясняльщик из меня еще тот ;)