![]() |
Как побороть погрешность при задании размерных свойств MovieClip (_width, _height)?
Вопрос, скорее к профи: movieclip залит битмапом(bitmapData) при помощи beginBitmapFill(). При последующем изменении размеров(._width, ._height) этого мувиклипа, в случае задания некоторых значений, реальные свойства клипа устанавливаются не точно. Пример: задаем клипу ширину 1475 (исходная 2000), а на деле клип преобретает _width = 1474.95 (такое значение видно в дебагере и при трейсе). Вопрос - как побороть? Как сделать чтобы ставишь 1475 и было 1475?
ps. все это нужно для того, чтобы сделать _плавное_ изменение размеров мувика... (остальные моменты вроде применения beginBitmapFill() вместо attachBitmap(), нужные smooting'и вроде учтены.. а иногда все равно еле заметно подергивается) |
Вложений: 1
Пример во вложении. Как-то слегка подергивается оно местами... В трейсе виден нюанс с размерами.
|
Вся незадача в том... что если изменять размеры таким способом, то в действительности все преобразования с клипом рассчитываются по принципу:
взять из матрицы преобразования коеффициент и умножить на исходное значение, естесственно, что при больших или "неудачных" размерах желаемого результата ингода не возможно добится (точности до 8-го знака не всегда хватит). Победить, я думаю, не удасться... Если бы не нужна была картинка, можно было бы каждый кадр програмно рисовать... (так, например реализована Iris transition), а так - не, не думаю... |
Посмотрел-повертел пример, попробовал на очень замедленном варианте просмотреть...
Проблема не в погрешности преобразования, думаю, а в общей для всех растровых анимаций (в отличие от "пленочных" кинотехнологий, напр.) проблеме масштабирования растрового изображения. В ТВ это называется "биение" - при масштабировании объекта "играют" пиксели, в особенности - на наклонных линиях с углом наклона, близким к 90 или 0 град. Общее же решение проблемы (хотя и не идеальное) - антиальясинг. Реализовать настоящий антиалиас (да еще и не просто Nearest Neighborhood, а, к примеру, Bicubic) средствами флэш нереально - BitmapData бесславно погибнет по производительности на второй тысяче пикселов при попиксельной обработке. Я бы попробовал на время зума фильтр Blur на минимуме включать. Если он только тоже провернет это дело. А скорее - отказался бы от плавного зумирования картинки, ведь судя по примеру, все равно фиксируются только крайние состояния, а между ними зум - только в качестве transition. Ну я бы другой транзишн и сделал - от масштабируемой рамочки а-ля фотошоп до "трехступенчатого" зума - т.е. трех фиксированных "степеней увеличения" с небольшой задержкой, - если ТЗ позволяет. |
И антиалисинг тут не причем.
Эта же проблема присутствует с векторнмыи объектами, я специально проверял. |
Сталкивался с этим неоднократно. Особенно в проектах, где требуется доскональная попиксельная точность. Лечил так:
присваивал значение (целое числовое), потом приравнивал этоже значение, но через округление. Код:
var newWidth : Number = 1475; |
но обычно повторное изменение на нормальные координаты и нажатие ентер помогает (хотя не всегда)
|
Цитата:
|
Понятно.
Я советую посмотреть в этот момент на значение _xscale для _width или _yscale для _height. Когда я тестировал, у меня они имели цельные значения. Учитывая, что данные свойства являются геттерами/сеттерами, мы не знаем, что именно происходит в момент присваивания ширины/высоты. Возможно, при больших размерах, происходит округление процентных размеров, а не пиксельных. Отсюда и глюк. |
Цитата:
глюк в данном примере никакого отношения к погрешности Флэша не имеет. При уменьшении окна он становится _заметнее_, при растяжке на фуллскрин - практически пропадает. Т.е. ошибка в выводе на устройство, обычная для антиалиаса. При флэшевых проблемах должно было бы быть наоборот. PS. Попробуйте, коллеги, плавно и медленно отзуммировать серую линию в 1 px на черном фоне _любым_ способом (хоть прямым выводом в видеопамять :) ) без антиальясинга - увидите, о чем я... |
при чем здесь антиалиасинг? на входе задаются целые числа, на выходе получаются дробные и виноват в этом (судя по вашим суждениям) антиалиасинг? :)
|
дело не в этих числах - их влияние на позиционирование, ИМХО, пренебрежимо мало по сравнению с обычным для любого растрового вывода (а вывод в монитор - это растровый вывод) "биения", и, судя по эксперименту, даже накопленная ошибка не выходит за пределы округления при масштабировании.
Обратите внимание на следующие особенности в приведенном примере: - при уменьшении эффект усиливается, и наоборот, хотя по логике вещей, если дело было бы в числах - было бы наоборот (грубо говоря, на ошибку флэша накладывалась бы еще и ошибка масштабирования на размер монитора этим же флэшем) - на деле все наоборот, при фуллскрине эффект (дефект, вернее) практически пропадает. - эффект наиболее сильно проявляется на наклонных, близких к 90 и 0 градусов, что как раз и характерно для проблемы "ступеньки" при растрировании - это заметно - при накопленной ошибке округления проявление этого эффекта было бы более или менее случайным - во всяком случае, на глаз. Можно ведь провести "обратный эксперимент" - внести искусственно бОльшую рандомную добавку к координатам. Эффект зрительно совершенно другой. - вертикали и горизонтали не так "дефектны" - на фуллскрине они вообще идеально масштабируются, как и вертикальные границы "кадриков" в примере, а на обычном размере фактически "играют" только за счет ошибок, естественных для масштабирования растрового изображения - т.е. становятся "влево-вправо" через равные промежутки времени (это заметно, если сильно замедлить приведенный пример) Опять-таки - вертикальные и горизонтальные линии "ступеньке" не подвержены, они сами масштабируются практически точно. Достаточно повернуть эту картинку на пару градусов - и границы "заиграют" точно так же "переливами". Посмотрите на любую тонкую окружность в флэшке. Попробуйте ее плавно увеличить или плавно уменьшить (да и не плавно - заметно то же самое). "макушка" и "бока" будут (в зависимости от монитора) или "срезаны", или "размыты". Вот то же самое творится и на любой границе яркостей, где угол близок к 0 или 90. Ровно то же самое происходит при "наезде" видеокамерой, поэтому опытные операторы (и 3D-дизайнеры, кстати ;) ) или избегают таких кадров, или применяют специальные приемы борьбы с этим дефектом. Только в ТВ это заметнее - там растр-то "крупнее"... Вы никогда не задумывались, почему практически ни в одной программе масштабирование/зум не реализуется вот таким способом - ведь программно это для авторов фотошопа или, напр., ACDSee - как нечего делать? И в идее - симпатично, вроде... если только не делать на каждый кадр бикубическое масштабирование или не юзать по полной программе возможности 3D-ускорителей, в коих единственных эта проблема решается (более-менее) с достойной производительностью. __ В конечном итоге задача (до появления мониторов с разрешением, превышающим разрешающую способность глаза, как минимум) неразрешима в общем виде. Квадратными пикселями не нарисовать точный круг, а масштабирование растрового изображения всегда приблизительно. Я понимаю удивление человека, столкнувшегося с тем, что вектор в итоге все равно - растр, и растровые эффекты на нем проявляются в полный рост, но вот на таких нюансах это и проявляется... слава Богу - редкий случай. PS. А вопрос стоит того, чтобы задать его разработчикам, ИМХО. Как бы то ни было - а этот дефект (что с Вашим объяснением, что с моим) стоит названия если не "баг", то, как мин., недоработка: и числа должны правильно выставляться, и возможность антиальясинга нормального для подобных задач вполне, IMHO, могла бы быть реализована на уровне стандартных фильтров. |
__Des, "смотрим в книгу видим фигу"?
Перечитайте Цитата:
Приведу аналогию. Допустим, одному пикслелю, мы назначаем синий цвет - 0x0000FF. Спустя какое то время, мы спрашиваем у пикселя его цвет и получаем 0x0000AA, хотя ни какие операции с ним не производили. Тут приходите вы и объясняете это тем, что у каждого монитора свои настройки и поэтому цвета отображаются по другому. |
Ну вы о разных вещах говорите.
__Des - про то, что 5 сотых пиксела - это не то, что заставляет картинку дергаться при анимации, а остальные про то, что геттер возвращает не то то значение, которое было получено сеттером. Я думаю, что, ответ простой - сеттер делает какие-то округления для того, чтобы много раз поменяв размер, установив потом скейл в 100% мы бы снова получили исходное, а не вычисленное после кучи округлений и погрешностей значение. Побочный эффект этих действий - не всегда точное соответсвие ввода выводу. Т.е. предположим, что мы 10 раз поменяли ширину объекта 13х13 пикселов с округлением до первого знака. Примерно так: 13х13 - 96% - 12.5х13 - 86% - 11.2х13 - 76% - 9.9х13 - 66% - 8.6 - 56% - 7.3х13 - 46% - 6х13 - 36% - 4.7х13 - 26% - 3.4х13 - 16% - 1.7х13 а теперь попытаемся восстановить в 100%, получим: 13,1х13. Так вот, очевидно, чтобы этого не случалось, сет-гет как-то по-другому работает, а как - надо уже у разработчиков спрашивать =) |
Ув. iNils, я решаю практическую задачу, поставленную в теме (куда я, собственно, и смотрел) - все это нужно для того, чтобы сделать _плавное_ изменение размеров мувика... Путь решения, предлагаемый самим автором темы в теме же, представляется мне (после собственного маленького исследования этой проблемы) неверным. Я обосновал и аргументировал, мне кажется, достаточно полно - почему. Могу и подробнее, если это интересно/нужно.
Разговор о проблемах/погрешностях геттера/сеттера - тоже интересная тема, но к решению задачи, поставленной в топике, не имеет, как я думаю, просто никакого отношения. Кстати, не было, кажется, ни одного толкового аргумента против моего объяснения, кроме "причем тут антиальясинг"? и "какое отношение имеет антиальясинг к физическим размерам?" (ну, вообще имеет, но в данном случае - никакого, как и погрешность физ. размеров - к наблюдаемому дефекту зуммирования). PS. Я еще один пренеприятный эффект обнаружил, похоже, имеющий отношение к теме. Вывод зависит от частоты обновления монитора. Медленно заскриптованное движение выглядит по-разному (с "дрыжками"/без) при разных частотах. Насколько я вижу, зависит от кратности FPS в флэше к частоте обновления изображения видеокарты, но поскольку точность FPS-а у Flash, похоже, далека от идеальной, и о синхронизации с видеокартой речи нет... :( Вот с этим точно не поборешься. И эффект зума этого тоже меняется при изменении частоты обновления видеокарты. |
2 wvxvw: Теорию о геттерах я уже выдвинул постами выши :) Только, другую. А ваша вызвает у меня сомнения, потому что я очень сомневаюсь, что флеш не хранит у себя первоначальные размеры, а каждый раз производит вычисления относительно текущего размера.
2 __Des: Нееее, задача была "Как побороть погрешность при задании размерных свойст", а для чего, вопрос уже вторичный :) |
iNils :
Смотри пост #7 =) Моя теория именно и заключается в том, что, гет-сет не присваивает напрямую значение, а каждый раз высчитывает его исходя из первоначально заданного. Последний - объяснение, почему нельзя просто присваивать значение. |
В 7-ом посте нет ни слова о геттерах/сеттерах. :)
Вроде все выяснил. Берем этот скрипт Код:
var size:Number = 2400;Код:
2400 | 2400Код:
2399 | 2398.950,99957275390625 * 2400 = 2398,974609375 Теперь переводим в твипсы (1/20 пикселя) 2398,974609375 * 20 = 47979,4921875 Отбрасываем дробную часть 47979,4921875 > 47979 Переводим обратно в пиксели 47979 / 20 = 2398,95 Что и получаем на выходе от _width. То есть дело не в точности знаков после запятой, а в системе хранения размеров флешом - твипсах. |
Господа, что касается задачи, __Des совершенно верно увидел ее истинное значение - конечно, нужно в первую очередь добиться плавности, а вопрос о погрешности я поднял лишь как шаг на пути ее решения (т.к. полагал, что дело именно в погрешности). Резюмируя, избавиться от данного дефекта невозможно, насколько я понимаю.
|
сорри, читал не все посты. может кое-что упустил
как я понял, в трейсе выдаётся не тот результат, который задаём. А что если делать проверку, и если результат не равен двигать на 0.1 пиксель к нужному результату? Сам проверять такое не решусь :D |
| Часовой пояс GMT +4, время: 03:58. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.