проблема 0x2K

19 views
Skip to first unread message

prof

unread,
Dec 14, 2006, 1:45:42 PM12/14/06
to ruF...@googlegroups.com

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

Итак, проблема выражается в том, что при определенных условиях метод draw
класса BitmapData не работает. То есть, в целевом битмапе никаких
изменений не происходит. Было понятно, что это как-то связано с
параметрами, передаваемыми в метод.
Путем несложных экспериментов выяснил, что на возникновение проблемы
влияют двевещи: размер исходного битмапа и масштаб. Допустим, наш исходный
битмап имеет размер X на Y. Коэффициенты масштабирования по осям - kx и
ky. Метод draw работает на ура, если одновременно выполняется:
kx*X < 8192;
ky*Y < 8192;

Поскольку 8192 == 0x2K, мы решили для себя называть эту проблему именно
так, как написано в subj.
Все остальные параметры никак не влияют на работоспособность метода draw
(по крайней мере, я ничего такого не обнаружил). Предвосхищая возможные
посылания меня в хэлп, где написано про ограничения в 2880 пикселов на
размер BitmapData, говорю, что это тут ни при чем.

Дальше - больше. Выяснилось, что если дальше увеличивать размер исходного
битмапа и/или масштаб, то метод draw снова начинает работать после
какого-то момента. Новые нехитрые эксперименты позволили понять, что на
самом деле метод работает, если одновременно выполняются снова два
условия, но немного другие:

2*i*0x2000 < kx*X < (2*i + 1)*0x2000;
2*j*0x2000 < ky*Y < (2*j + 1)*0x2000;

Здесь i, j = 0, 1, 2...

Можно это условие выразить и по-другому:

(int(kx*X) & 0x2000) == 0;
(int(ky*Y) & 0x2000) == 0;

То есть, в результате умножения размера и масштаба, приведенному к целому
типу, 14-й бит отвечает за работоспособность метода draw().

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

В общем, мнения - в студию!

--
prof

Nox Noctis

unread,
Dec 14, 2006, 1:56:26 PM12/14/06
to ruF...@googlegroups.com
> В очередной раз игрался с битмапами и в очередной раз натолкнулся на эту

а кинь, пожалуйста, код, который не работает.
так легче будет понять и удивиться :)

--
Michael Antipin
______________________________________________________________________
n...@design.ru | http://www.artlebedev.ru | http://www.noregret.org

prof

unread,
Dec 14, 2006, 2:50:14 PM12/14/06
to ruF...@googlegroups.com

> а кинь, пожалуйста, код, который не работает.

Код на AS3, но это и в AS2 не работает.

var s : BitmapData = new BitmapData(1024, 1024, true, 0xFFAAAAFF);
var t : BitmapData = new BitmapData(100, 100, true, 0);
var m : Matrix = new Matrix(10, 0, 0, 10);
t.draw(s, m, null, null, new Rectangle(0, 0, 50, 50), true);

Этот вариант не будет работать. То есть trace(t.getPixel(25,
25).toString(16)) выдаст 0.

Но если масштабирование поставить до 8, то будет работать. Снова будет
работать, если увеличение будет от 16 до 24. Ну и так дальше.

--
prof

zh.

unread,
Dec 14, 2006, 3:48:01 PM12/14/06
to prof
prof> мы решили для себя называть эту проблему именно так, как написано в subj.
отправь адобавцам баг-репорт.
или в вишлист напиши, чтобы багу исправили!

--> zh. ну ладно, согласен, я тоже иногда туда хочу. <--

prof

unread,
Dec 15, 2006, 12:17:29 AM12/15/06
to ruF...@googlegroups.com
> отправь адобавцам баг-репорт.
> или в вишлист напиши, чтобы багу исправили!

Это точно бага? А не фича?

--
prof

prof

unread,
Dec 15, 2006, 2:20:13 AM12/15/06
to ruF...@googlegroups.com

В продолжение моего письма.

Собственно, четкое понимание того, когда возникает баг, это хорошо, но
практический интререс представляют возможные методы обхода.
Я не придумал ничего лучшего, чем перед вызовом draw сначала копировать
часть исходного битмапа в промежуточный буфер. То есть примерно так:

public static function draw_fix(target:BitmapData, source:BitmapData,
matrix:Matrix = null, colorTransform:ColorTransform = null,
blendMode:String = null, clipRect:Rectangle = null, smoothing:Boolean =
false)
{
var m : Matrix = matrix ? matrix : new Matrix();
var cRect : Rectangle = clipRect ? clipRect : target.rect;
var sourceRect : Rectangle = new Rectangle((cRect.x - m.tx)*m.a,
(cRect.y - m.ty)*m.d, cRect.width*m.a, cRect.height*m.d);
var buffer : BitmapData = new BitmapData(sourceRect.width,
sourceRect.height, true, 0);
buffer.copyPixels(source, sourceRect, new Point());

var m2 : Matrix = new Matrix(m.a, m.b, m.c, m.d, cRect.x, cRect.y);
target.draw(buffer, m2, colorTransform, blendMode, clipRect, smoothing);
}

Код непроверенный, точно не учитывает вращение, да и за остальное не
уверен. Приведен только чтобы показать принцип. Довести его до рабочего
состояния можно, думаю, больших вопросов не возникнет.
Кроме одного (по крайней мере, у меня он возникает):
А не приведет ли предварительное копирование в буфер части исходного
битмапа к "краевым" эффектам в конечном изображении? И если это так (а я
думаю, что это так, как минимум, в случае, если smoothing == true), как с
этим бороться?

--
prof

iFrame

unread,
Dec 15, 2006, 5:56:28 AM12/15/06
to ruF...@googlegroups.com
Здрасте!
До чего же странные у вас потребности....
Какие нужды требуют от вас таких больших размеров, если не секрет?
В Хелпе написано о 2880, а это значит, что если вы пытаетесь
использовать значения больше, то вся ответственность(или что то
другое) ложится на ваши плечи. И по этому речи о багах и баг-репортах
не может быть. :)

--
/*
Oleg Galaburda
mailto:bur...@gmail.com
ICQ:289297363

Торжественно клянусь в том, что с этого времени буду использовать
Get/Set методы только там где это действительно необходимо!. (с) a_[w]
*/

prof

unread,
Dec 15, 2006, 6:39:50 AM12/15/06
to ruF...@googlegroups.com
> До чего же странные у вас потребности....
> Какие нужды требуют от вас таких больших размеров, если не секрет?
> В Хелпе написано о 2880, а это значит, что если вы пытаетесь
> использовать значения больше, то вся ответственность(или что то
> другое) ложится на ваши плечи. И по этому речи о багах и баг-репортах
> не может быть. :)

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

Нужды тоже вполне реальные. Нечто подобное yahoo maps. Не вижу ничего
особенно удивительного в том, что мне нужно вывести на экран увеличенную в
4 раза ЧАСТЬ загруженного изображения. Даже будучи увеличенной, эта часть
значительно меньше, чем 2880х2880. Но сделать этого напрямую я не могу
из-за описанного бага.

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

Так что, очень похоже, что это именно баг, и что без баг-репортов он не
будет починен и в 9-ке.

--
prof

iFrame

unread,
Dec 15, 2006, 7:57:04 AM12/15/06
to ruF...@googlegroups.com
> Нужды тоже вполне реальные. Нечто подобное yahoo maps. Не вижу ничего
> особенно удивительного в том, что мне нужно вывести на экран увеличенную в
> 4 раза ЧАСТЬ загруженного изображения. Даже будучи увеличенной, эта часть
> значительно меньше, чем 2880х2880. Но сделать этого напрямую я не могу
> из-за описанного бага.

mc.attachBitmap(bmp, 1);
mc._width = 4000;
mc._height = 4000;
или _xscale, _yscale или куча других способов. :)

> Далее. Если в моем примере вы найдете хоть одно число, большее или равное

> В своем первом письме я отдельно отметил,
> что я знаю про 2880, и это ограничение в данном случае не играет никакой
> роли.

Вы не найдёте в моём письме фразы отвечающей критерию "вы не знаете"
или подобную. :)

А по поводу части или полного изображения. Так по моему, не важно что
и с какими параметрами вы фотографируете. Более важно что выходит из
этого. :)
А, вы пытаетесь получить Битмап по размерам больший за 2880. Может
нужно начать думать о том, зачем сделали ограничение в 2880 пикселей?

prof

unread,
Dec 15, 2006, 9:59:00 AM12/15/06
to ruF...@googlegroups.com
>> нужно вывести на экран увеличенную в
>> 4 раза ЧАСТЬ загруженного изображения. Даже будучи увеличенной, эта
>> часть
>> значительно меньше, чем 2880х2880. Но сделать этого напрямую я не могу
>> из-за описанного бага.
>
> mc.attachBitmap(bmp, 1);
> mc._width = 4000;
> mc._height = 4000;
> или _xscale, _yscale или куча других способов. :)

А вы вот так попробуйте:
mc.attachBitmap(bmp, 1);
mc._width = 0x2100;
mc._x = 0 - 0x2000;

Я говорил о проблеме 0x2K, а не 4000.

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

> А по поводу части или полного изображения. Так по моему, не важно что
> и с какими параметрами вы фотографируете. Более важно что выходит из
> этого. :)

Я написал в первом письме, в каких ситуациях возникает баг. Не "по-моему",
а по результатам экспериментов.

> А, вы пытаетесь получить Битмап по размерам больший за 2880. Может
> нужно начать думать о том, зачем сделали ограничение в 2880 пикселей?

Я не пытаюсь получить битмап, "по размерам больший за 2880". Где вы это
увидели?

var s : BitmapData = new BitmapData(1024, 1024, true, 0xFFAAAAFF);
var t : BitmapData = new BitmapData(100, 100, true, 0);
var m : Matrix = new Matrix(10, 0, 0, 10);
t.draw(s, m, null, null, new Rectangle(0, 0, 50, 50), true);

Где тут тот битмап, о котором вы говорите?
Еще раз, если вам лень было внимательно прочитать мое письмо до конца:
если в этом примере поставить масштаб не 10, а 15 - то все будет нормально.

Я не знаю, может и "нужно начать думать о том, зачем сделали ограничение в
2880 пикселей". Но я не думаю. Есть такое ограничение - я его принимаю.
Почему оно такое - мне не важно. И если оно меня действительно как-то
ограничивает - я ищу решение, которое и меня устроит, и ограничение не
нарушит. Но это совсем другая проблема. Это проблема "2880". А я наткнулся
на "0x2K" :)

--
prof

prof

unread,
Dec 15, 2006, 12:13:25 PM12/15/06
to ruFlash
> если в этом примере поставить масштаб не 10, а 15 - то все будет нормально.

Ошибся, конечно. Заработает после 16.

iFrame

unread,
Dec 15, 2006, 12:16:29 PM12/15/06
to ruF...@googlegroups.com
> А вы вот так попробуйте:
> mc.attachBitmap(bmp, 1);
> mc._width = 0x2100;
> mc._x = 0 - 0x2000;

попробовал:
var bmp = new flash.display.BitmapData(1024, 1024, false, 0xff0000);
this.createEmptyMovieClip('mc', 1);


mc.attachBitmap(bmp, 1);
mc._width = 0x2100;

mc._x = Stage.width/2-mc._width;
trace([mc._width, mc._height]);

:) всё отлично работает.
правда при
mc._width = 0x3000;
mc._width = 0x4000;
появляются нелогичные вещи но, на это, по моему, есть причина... :)

> Я говорил о проблеме 0x2K, а не 4000.

не важно. если есть проблема, то она есть, а если нё нет, то... :-/
соответственно(ненавижу это слово - слишком много согласных рядом).

> Кроме того, не от нечего делать пришел я к работе с BitmapData. Ни
> предложенный вами способ, ни какой другой из той кучи, которую вы
> упомянули, не обеспечивает нужного быстродействия.

я упомянул 1(один, one, ein, un, uno, solo, 0x1) способ. :)

> Я написал в первом письме, в каких ситуациях возникает баг. Не "по-моему",
> а по результатам экспериментов.

Хорошо, что хоть кто то эксперементирует - я к этому отношусь философски.

> Я не пытаюсь получить битмап, "по размерам больший за 2880". Где вы это увидели?

Я почувствовал колебания в силе... в этом районе:


var m:Matrix = new Matrix(10, 0, 0, 10);

a, d - scale.

и вполне возможно, что механизм BitmapData.draw() внутренне устроен
немного не так как вы этого хотели/ожидали...


> Я не знаю, может и "нужно начать думать о том, зачем сделали ограничение в
> 2880 пикселей". Но я не думаю. Есть такое ограничение - я его принимаю.

Сугубо моё личное мнение и кто то с ним может быть не согласен - зря.

Я откланяюсь т.к. не способен решать подобные 0х2К проблемы и
генерировать конструктивные мысли при столь обширном взгляде на бытиё.

prof

unread,
Dec 15, 2006, 12:57:52 PM12/15/06
to ruF...@googlegroups.com

>> А вы вот так попробуйте:
> попробовал:
> var bmp = new flash.display.BitmapData(1024, 1024, false, 0xff0000);
> this.createEmptyMovieClip('mc', 1);
> mc.attachBitmap(bmp, 1);
> mc._width = 0x2100;
> mc._x = Stage.width/2-mc._width;
> trace([mc._width, mc._height]);

mc._x = 0 - 0x2001; - ЭТО ВАЖНО !!!

> :) всё отлично работает.
> правда при
> mc._width = 0x3000;
> mc._width = 0x4000;
> появляются нелогичные вещи но, на это, по моему, есть причина... :)

Расскажите мне, в чем она, причина, по-вашему? почему вдруг мувик лежит в
одном месте, а окрашенные пиксели (та самая битмап дата) - в другом?
И посмотрите, что будет с вашим примером при mc._width = 0x5000;
Или при 0x5000 причины уже нет?

>> Я говорил о проблеме 0x2K, а не 4000.
> не важно. если есть проблема, то она есть, а если нё нет, то... :-/

Ну вы ведь признали, что она есть, в предыдущем предложении. Как же так?

>> предложенный вами способ, ни какой другой из той кучи, которую вы

> я упомянул 1(один, one, ein, un, uno, solo, 0x1) способ. :)

Да? Присмотритесь повнимательней:

>>> mc.attachBitmap(bmp, 1);
>>> mc._width = 4000;
>>> mc._height = 4000;
>>> или _xscale, _yscale или куча других способов.

Один предложили, и кучу упомянули, как я и говорил.

>> Я не пытаюсь получить битмап, "по размерам больший за 2880". Где вы это
>> увидели?
> Я почувствовал колебания в силе... в этом районе:
> var m:Matrix = new Matrix(10, 0, 0, 10);
> a, d - scale.

Да, это масштаб. Ну и что, мне нельзя увеличить 1 пиксель в 10 раз? Но при
этом в 20 - можно? Где логика?

> и вполне возможно, что механизм BitmapData.draw() внутренне устроен
> немного не так как вы этого хотели/ожидали...

Да, именно об этом я и говорю. Он содержит либо баг, либо фичу, которая
проявляется так, как я описал в первом письме.

>> Я не знаю, может и "нужно начать думать о том, зачем сделали
>> ограничение в
>> 2880 пикселей". Но я не думаю. Есть такое ограничение - я его принимаю.
> Сугубо моё личное мнение и кто то с ним может быть не согласен - зря.

Да поймите вы, это из другой области ограничение, я его не нарушаю.

--
prof

Reply all
Reply to author
Forward
0 new messages