Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Прогресс создания ByteArray (http://www.flasher.ru/forum/showthread.php?t=210899)

Alex626 23.05.2015 14:10

Прогресс кодирования BitmapData в ByteArray и далее файл
 
Добрый день, господа!

У меня в приложении создаётся объект BitmapData большого размера, а затем конвертируется в ByteArray через BitmapData.encode(), чтобы затем сохранить в JPEG-файл. Процесс занимает до 10 секунд. Хотелось бы создать прогресс-бар, или что-то в этом духе, который показывал бы прогресс перекодировки. Возможно ли такое?

И попутный вопрос: можно ли заранее узнать максимально возможный размер BitmapData на машине пользователя, если ролик компилировался под последний Flash Player? А то у меня слайдер стоит, который позволяет менять масштаб снимаемого BitmapData, и можно сделать, например, масштаб 3:1. Но разрешение при этом подскакивает до потолка (20х20 тысяч пикселей и выше), и часто бывает, что после определённого коэффициента увеличения (2:1 и выше) выскакивает ошибка BitmapData.

Zebestov 23.05.2015 14:32

Процесс этот синхронный, потому в одно движение ничего не выйдет.
Если это возможно — разбей его на части.
Если нет, но очень нужно — Worker

Alex626 23.05.2015 17:11

А можно подробнее, что именно делать с этим Worker?

И, для второго вопроса - можно как-либо оценивать доступную для BitmapData память с помощью System.totalMemory?

undefined 23.05.2015 21:36

Цитата:

А можно подробнее, что именно делать с этим Worker?
Выносить все,что тормозит в отдельный swf и пихать её в отдельный воркер.
Но ИМХО,тут проще будет нарезать большую битмапДату на несколько маленьких и декодировать их последовательно. Перед скармливанием jpeg-энкодеру все предварительно слить в один ByteArray

Alex626 24.05.2015 14:37

Цитата:

Сообщение от undefined (Сообщение 1182706)
тут проще будет нарезать большую битмапДату на несколько маленьких и декодировать их последовательно. Перед скармливанием jpeg-энкодеру все предварительно слить в один ByteArray

Это мне нравится. Это решило бы и второй вопрос - с максимальным размером BitmapData. Скажите, как правильно оперировать функцией BitmapData.Draw для снятия снимков с разных частей одного и того-же DisplayObject'a? Ну вот, к примеру, я хочу разбить свой спрайт на сетку из BitmapData размером 10х10. Мне надо как-то с помощью трансформ-матрицы задавать смещение? И ещё, если учитывать, что трансформ-матрицей я задаю Scale, который увеличивает масштаб съёмки.

undefined 24.05.2015 17:54

А блин я не так понял вопрос.Думал ты с помощью стороннего энкодера в jpg перегоняешь.Тогда(в теории) можно взять этот энкодер и подкрутить его чтоб жал кусуками

illuzor 24.05.2015 18:06

undefined, зачем советовать устаревший тормозной энкодер, когда есть нативный?

Alex626 24.05.2015 19:21

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

У меня система такая:

1) есть спрайт размером 5000х5000 - предположим
2) я создаю BitmapData размером 5000*scale - переменная scale отвечает за масштаб съёмки
3) я создаю матрицу трансформации, и устанавливаю matrix.scale(scale, scale);
4) делаю BitmapData.Draw с заданной выше матрицей трансформации

И тут возникает первая проблема: если размер BitmapData будет больше чем определённое число (если scale=3, то габариты будут 15000х15000) - выходит ошибка *2015*. Тогда ловлю исключение, понижаю коэффициент scale и начинаю заново.

5) создаю byteArray и JPEGEncoderOptions
6) делаю BitmapData.encode на этот byteArray, с размером квадрата 5000*scale

Тут я хочу отследить прогресс создания файла и как-то вывести его на экран.

7) сохраняю через FileReference



Очевидно узкое место - слишком большое разрешение BitmapData, как результат - долгая перекодировка и возможность возникновения ошибки BitmapData (типа нехватка памяти в ОС). Поэтому хочу сделать много разных BitmapData, массивом, и потом каждый по отдельности перекодировать в свой byteArray, и в конце все их склеить в один большой и вывести в файл.

Как мне нарезать мой спрайт на части? Чем пользоваться? В плане, какие параметры юзать для матрицы трансформации и для BitmapData.Draw?

undefined 24.05.2015 19:40

illuzor, штатный энкодер синхронный раз,
принимает на входе BitmapData а не byteArray два,
реализация недоступна три

Alex626, это я поторопился.Думал метод encode как раз перегоняет битмапдату в ByteArray. В твоем случае нарезка большой битмапдаты скорее всего не прокатит. Т.к. если нарезать её, перегнать куски в ByteArray и потом все назад склеить тупой конкатенацией исходную битмапдату скорее всего не получишь.
Поэтому говорю посмотри исходники энкодера по моей ссылке.Там кодирование идет за счет последовательного кодирования блоков размером 8х8.Немного добработать напильником и можно сделать чтоб за раз кодировалось не все, а лишь кусок.
Но ИМХО это все изобретение велосипеда.Лучше прислушаться к совету Zebestov'а - сделать отдельную флэшку-энкодер и грузить её отдельным воркером. Они как раз для таких ситуаций и были придуманы

UPd:Особо обольщаться по поводу вокеров не стоит.Отдельный воркер для энкода даст только возможность показать какую-то анимацию пока идет кодирование т.к. сама операцию как была так и осталась синхронной и прогресс так просто не получишь.Решение - кодировать по частям как я описал выше. Либо как-то узнавать тактовую частоту проца юзера и из неё как-нибудь вычислять сколько времени может занять вся операция

upd2:
Цитата:

И тут возникает первая проблема: если размер BitmapData будет больше чем определённое число (если scale=3, то габариты будут 15000х15000) - выходит ошибка *2015*. Тогда ловлю исключение, понижаю коэффициент scale и начинаю заново.
Так в чем собственно проблема?

Alex626 24.05.2015 21:15

Цитата:

Сообщение от undefined (Сообщение 1182732)

Так в чем собственно проблема?

Хотелось бы заранее как-то вычислять максимально доступное разрешение. У меня в интерфейсе стоит слайдер для выбора параметра scale (от 0.3 до 3). Каждый раз через try конечно можно (с выводом сообщения юзеру "выбранный размер недоступен. масштабирование было уменьшено"). Но ведь если машина слабая, и доступно только разрешение, скажем, 1.2, то юзеру который выберет 3, придётся несколько раз нажимать на кнопку и читать сообщение. Либо, как вариант, можно конечно зациклить создание BitmapData, ловить исключение и уменьшать коэффициент понемногу - до момента, когда выбор будет оптимален. Но ведь всё это костыли.

Если только каким-то макаром разбить битмапдату на куски и склеить конкатенацией (но это невозможно, да?) или хоть высчитать объём доступной памяти и по нему посчитать максимальный коэффициент Scale. Эх, вот ведь придумал сложности :D

Добавлено через 3 минуты
Кстати, я пробовал уже этот энкодер, что из ссылки. Ещё пару недель назад. Как и говорил, работает дико медленно, и памяти жрёт непозволительно много. Если нативный кодирует за 10 секунд, то этот работает над тем же материалом больше минуты, и частенько выдаёт "нехватку памяти".


Часовой пояс GMT +4, время: 09:18.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.