Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 31.07.2011, 19:44
Gantenbain вне форума Посмотреть профиль Отправить личное сообщение для Gantenbain Найти все сообщения от Gantenbain
  № 1  
Ответить с цитированием
Gantenbain

Регистрация: Jul 2011
Сообщений: 32
По умолчанию Как получить адреса пикселей BitmapData?

Всем - добрый день!

Вопрос уже задавал на другом форуме, однако специализация и представительность этого форума внушают мне столь обширные надежды, что можно и нескромно повториться.
Задача - получить адреса пикселей BitmapData до помещения связанного объекта Bitmap в список отображения (для реализации специфической заливки отображаемой фигуры, созданной средствами векторной графики).
Однако, единственный способ, который пришел мне в голову, не работает:

Код:
var tmpSh:Shape = new Shape();
tmpSh.graphics.beginFill(0xFF00FF, 1);
tmpSh.graphics.drawPath(commands, data);
tmpSh.graphics.endFill();
var r:Rectangle = tmpSh.getRect(stage);
var pt:Point = r.topLeft;
var pixelValue:uint, pixelValueMask:uint, i:int = 0, j:int = 0;
var bmpdata:BitmapData = new BitmapData(r.width, r.height, false, 0xFF0000); 
bmpdata.draw(tmpSh);
var arr:Vector.<String> = new Vector.<String>();
for (i = 0; i < r.width-1; i++) {
  for (j = 0; j < r.height-1; j++) {
    pixelValue =  bmpdata.getPixel(i, j);
    if (arr.length == 0 || arr.indexOf(("0x"+pixelValue.toString(16))) < 0)  arr.push("0x"+ pixelValue.toString(16));
  } 
}
trace(arr);
В массиве присутствуют значения цвета лишь 0xFF0000 (фигура, заданная drawPath(commands, data), естественно, отрисовывается правильно после добавления ее в контейнер отображения). Есть ли какой-либо способ достать ее пиксели не отображая ее?

Старый 31.07.2011, 21:32
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 2  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Код AS3:
var tmpSh:Shape = new Shape();
tmpSh.graphics.beginFill(0xFF00FF, 1);
tmpSh.graphics.drawRect(5, 5, 20, 20);// drawPath(commands, data);
tmpSh.graphics.endFill();
var pixelValue:uint, pixelValueMask:uint, i:int = 0, j:int = 0;
var bmpdata:BitmapData = new BitmapData(tmpSh.width, tmpSh.height, false, 0xFF0000); 
bmpdata.draw(tmpSh);
var arr:Vector.<String> = new Vector.<String>();
for (i = 0; i < tmpSh.width-1; i++) {
	for (j = 0; j < tmpSh.height-1; j++) {
		pixelValue =  bmpdata.getPixel(i, j);
		if (arr.length == 0 || arr.indexOf(("0x"+pixelValue.toString(16))) < 0)  arr.push("0x"+ pixelValue.toString(16));
	} 
}
trace(arr); // 0xff0000,0xff00ff
__________________
Reality.getBounds(this);

Старый 01.08.2011, 09:40
Gantenbain вне форума Посмотреть профиль Отправить личное сообщение для Gantenbain Найти все сообщения от Gantenbain
  № 3  
Ответить с цитированием
Gantenbain

Регистрация: Jul 2011
Сообщений: 32
Спасибо, за оперативный ответ.
Думаю, Вас бы очень повеселило выражение моего лица, с которым смотрю на
Цитата:
// 0xff0000,0xff00ff
Возможно, что проблема связана с тем, что "заливку" "большой" Bitmap провожу в несколько этапов, с помощью "внутренней" функции, в качестве параметра которой передаю this
Код:
var paintSh:Function = function(bmp:Bitmap):void {
Однако, некоторый толчок мысли задан...
P.S. "Внутренняя" функция ни при чем - квадрат возвращает 2 цвета...Что-то возле drawPath...
P.P.S. Если определяю параметры commands, data внутри "внутренней" функции, то нахожу 2 цвета в bitmapData, при попытке передать параметры извне - 1 цвет.

Добавлено через 1 час 43 минуты
Все понял. paintSh(this) в моей реализации передает ссылку на глобальный объект вместо экземпляра класса. Досадный ляп. Большое спасибо, Wolsh.
P.S. И это не то . Так не долго в рассудке повредиться

Добавлено через 3 часа 57 минут
Несмотря на то, что, благодаря Wolsh, доступ к адресам пикселей оказался открыт , академический интерес к проблеме остался (пример сугубо условный):
Код AS3:
package game
{
	import flash.display.Sprite;
 
	public class  Example extends Sprite
	{
		public function Example() {
			var er:MyClass = new MyClass();
			addChild(er);
		}
	}
 
}
Код AS3:
package game
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.geom.Point;
	import flash.geom.Rectangle;
 
	public class MyClass extends Bitmap 
	{
		private var commands:Vector.<int>;
		private var data:Vector.<Number>;
 
		public function MyClass() {
			var thisbitmapdata:BitmapData = new BitmapData(800, 600, true, 0x80FFFFFF);
			this.bitmapData = thisbitmapdata;
			commands = Vector.<int>([1, 2, 2, 2, 2]);
			data = Vector.<Number>([5, 5, 20, 5, 20, 25, 5, 25, 5, 5]);
			var i:int;
			var paintBm:Function = function(bmp:Bitmap):void {
				trace(bmp);
				var tmpSh:Shape = new Shape();
				tmpSh.graphics.beginFill(0xFF00FF, 1);
				tmpSh.graphics.drawPath(commands, data);
				//tmpSh.graphics.drawPath(Vector.<int>([1, 2, 2, 2, 2]), Vector.<Number>([5, 5, 20, 5, 20, 25, 5, 25, 5, 5]));
				tmpSh.graphics.endFill();
				var r:Rectangle = tmpSh.getRect(stage);
				var pixelValue:uint;
				var arr:Vector.<String> = new Vector.<String>();
				var bmpdata:BitmapData = new BitmapData(r.width, r.height, false, 0xFF0000); 
				bmpdata.draw(tmpSh);
				for (var m:int = 0; m < r.width-1; m++) {
					for (var j:int = 0; j < r.height-1; j++) {
						pixelValue =  bmpdata.getPixel(m, j);
				        if (arr.length == 0 || arr.indexOf(("0x"+pixelValue.toString(16))) < 0)  arr.push("0x"+ pixelValue.toString(16));
					} 
				}
				trace(arr);
				bmp.bitmapData.draw(tmpSh);
			}
			while(i < 660) {
			for each (var e:Number in data) data[data.indexOf(e)] = e + i; 
			paintBm(this);
			i += 50;
			}
		}
	}
 
}
Перекинем комментарий с одного "tmpSh.graphics.drawPath(" на другой и видим 2 цвета, вместо одного (?). Попытки передать в функцию параметры, или, создав новые массивы внутри функции, скопировать в них данные из внешних массивов - тупиковые.

Добавлено через 7 часов 3 минуты
Ну и теперь совсем лишившее меня каких-либо идей обстоятельство: при попытке проследить связи объектов теми средствами, что дает FlashDeveloper (точки останова ставил на <bmpdata.draw(tmpSh);> и <paintBm(this);>), обнаружил изменение в поведении программы - теперь выводятся все пикселы массива..., т.е. пошаговое действие отличается от нормальной работы. Внятного объяснения не имею.

Добавлено через 7 часов 38 минут
В общем, размещение
Код AS3:
var tmpSh:Shape = new Shape();
среди полей класса, а не во внутренней функции, решает проблему. Тему можно закрыть.


Последний раз редактировалось Gantenbain; 01.08.2011 в 16:43.
Старый 01.08.2011, 18:03
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 4  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
В 10 плеере у БитмапДаты появился метод getVector, возвращающий Вектор с ARGB-значениями всех пикселей заданного прямоугольника битмапдаты. Например
Код AS3:
......
var tmpSh:Shape = new Shape();
tmpSh.graphics.beginFill(0xFF00FF, 1);
tmpSh.graphics.drawRect(5, 5, 20, 20);// drawPath(commands, data);
tmpSh.graphics.endFill();
var pixelValue:uint, pixelValueMask:uint, i:int = 0, j:int = 0;
var bmpdata:BitmapData = new BitmapData(tmpSh.width, tmpSh.height, false, 0xFF0000); 
bmpdata.draw(tmpSh);
var pixels:Vector.<uint> = bmpdata.getVector(bmpdata.rect);
var palette:Vector.<uint> = pixels.sort(descSort).filter(uniqueSort);
trace( vectorColorsToString(palette, 6, "#") );
}
 
private function uniqueSort(item:uint, index:int, vector:Vector.<uint>):Boolean
{
	if (index === 0) return true;
	return (item !== vector[index - 1]);
}
 
private function descSort(x:uint, y:uint):Number
{
	if (x < y) return 1;
	if (x > y) return -1;
	return 0;
}
 
private function vectorColorsToString(vector:Vector.<uint>, digits:uint = 6, prefix:String = "0x"):Vector.<String>
{
	var colors:Vector.<String> = new Vector.<String>();
	for (var i:uint = 0; i < vector.length; i++)
	{
		var color:String = vector[i].toString(16);
		color = "00000000" + color;
		color = color.substr(color.length - digits, digits);
		colors.push(prefix + color);
	}
	return colors;
}
__________________
Reality.getBounds(this);

Старый 01.08.2011, 21:40
Gantenbain вне форума Посмотреть профиль Отправить личное сообщение для Gantenbain Найти все сообщения от Gantenbain
  № 5  
Ответить с цитированием
Gantenbain

Регистрация: Jul 2011
Сообщений: 32
Да, я пробовал и этим вариантом снимать данные с BitmapData...
Кстати, должен покаяться (как бы ни было досадно это делать) - поторопился отрапортовать, что удовлетворил свой "академический интерес" ... Давно не ощущал себя в такой прострации:
чтобы не гонять бессмысленные циклы, изменим
Код AS3:
while(i < 150)
, добавим переменную
Код AS3:
var trigg:int = 0;
и внутрь var paintBm:
Код AS3:
trigg = 1 - trigg;
var vvv:Vector.<Vector.<Number>> = Vector.<Vector.<Number>>([Vector.<Number>([5, 5, 20, 5, 20, 25, 5, 25, 5, 5]), Vector.<Number>([15, 15, 30, 15, 30, 35, 15, 35, 15, 15])]);
tmpSh.graphics.drawPath(commands, vvv[trigg]);
и в итоге:
trigg:0; color:0xff0000,0xff00ff
trigg:1; color:0xff0000
trigg:0; color:0xff0000,0xff00ff

Цвета второго прямоугольника игнорированы при любом начальном значении trigg...
Однако, если исказим углы прямоугольников
Код AS3:
var vvv:Vector.<Vector.<Number>> = Vector.<Vector.<Number>>([Vector.<Number>([7, 5, 20, 5, 20, 25, 5, 25, 7, 5]), Vector.<Number>([10, 15, 30, 15, 30, 35, 15, 35, 10, 15])]);
то, надо полагать, благодаря размытию, получим:
trigg:0; color:0xff0000,0xff001f,0xff003f,0xff007f,0xff009f,0xff00bf,0xff00ff
trigg:1; color:0xff0000,0xff00df,0xff009f,0xff005f,0xff001f,0xff00ff
trigg:0; color:0xff0000,0xff001f,0xff003f,0xff007f,0xff009f,0xff00bf,0xff00ff

Попытки отследить связи через отладчик меня не навели ни на какие выводы о причинах такого загадочного поведения... Возможно был недостаточно внимателен, возможно мое знание flash'a and AS изобилует пробелами, что вполне вероятно, т.к. увлекся этим недавно,... но озадачен. Возможно, допускаю некое хулиганство в конструкторе класса, но мне оно не очевидно.

Добавлено через 20 часов 4 минуты
Если код изменить таким образом
Код AS3:
public function MyClass() {
 			var thisbitmapdata:BitmapData = new BitmapData(800, 600, true, 0x80FFFFFF);
			this.bitmapData = thisbitmapdata;
			var commands:Vector.<int> = Vector.<int>([1, 2, 2, 2, 2]);
			var data:Vector.<Number> = Vector.<Number>([5, 5, 19, 5, 19, 19, 5, 19, 5, 5]);
			var i:int = 0;
			var pixelValue:uint = 0;
 
			var paintBm:Function = function(bmp:Bitmap):void {
				var arr:Vector.<String> = new Vector.<String>();
	                        var tmpSh:Shape = new Shape();
				tmpSh.graphics.beginFill(0xFF00FF, 1);
				tmpSh.graphics.drawPath(commands, data);
				var r:Rectangle = tmpSh.getBounds(stage);
				var w:int = r.width;
				var h:int = r.height;
				var bmpdata:BitmapData = new BitmapData(w, h, false, 0xFF0000); 
				bmpdata.draw(tmpSh);
				var mtr:Matrix = new Matrix(1, 0, 0, 1, 30 + i*10, r.topLeft.y);
				var aSh:Bitmap = new Bitmap();
				var aShbmpdata:BitmapData = new BitmapData(w, h, false, 0x00DDCC); 
 
				for (var m:int = 0; m < w; m++) {
					for (var j:int = 0; j < h; j++) {
						pixelValue =  bmpdata.getPixel(m, j);
						if (pixelValue == 0xFF00FF) aShbmpdata.setPixel(m, j, pixelValue);
				        if (arr.length == 0 || arr.indexOf(("0x"+pixelValue.toString(16))) < 0)  arr.push("0x"+ pixelValue.toString(16));
					} 
				}
 
				arr.splice(0, arr.length);
				aSh.bitmapData = aShbmpdata;
				bmp.bitmapData.draw(tmpSh);
				bmp.bitmapData.draw(aSh, mtr, null, null, null, false);
				tmpSh.graphics.clear();
				bmpdata.dispose();
			}
			while(i < 20) {
			for (var e:int = 0; e < data.length; e++ ) {
				data[e] += i; 
			}
			paintBm(this);
			i +=2;
			}
		}
то создается впечатление, что метод getPixel возвращает пиксели из области, которую объект успешно покидает, и которая определяется начальным getBounds объекта. Не придумал лучшего, как зарегистрировать баг в базе данных Адоба #2933259, но, судя по датам уже имеющихся багов, это надолго.. Я не вижу, в чем может быть некорректность используемого мной приема, а отказываться от него жаль, т.к. сильно экономит код.

Старый 03.08.2011, 10:22
Gantenbain вне форума Посмотреть профиль Отправить личное сообщение для Gantenbain Найти все сообщения от Gantenbain
  № 6  
Ответить с цитированием
Gantenbain

Регистрация: Jul 2011
Сообщений: 32
Question Пока считаю это багом

Получить правильные значения адресов пикселей можно таким образом:
Код AS3:
bmpdata.draw(tmpSh, new Matrix(1, 0, 0, 1, -data[0], -data[1]), null, null, null, false);
но, имхо, это противоречит концепции класса. Пока считаю это багом. Стоит ли использовать, сомневаюсь. Имеются другие мнения?
Миниатюры
Нажмите на изображение для увеличения
Название: pix2.PNG
Просмотров: 249
Размер:	5.4 Кб
ID:	26882  

Старый 03.08.2011, 12:56
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 7  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
1. Вынесите вложенную функцию. Это – зло в 99% случаев, и лучше так не делать никогда, пока не припрет необходимость.
2. Проблема мне видится в использовании Ректангла, тем более взятого в системе координат стейджа. Я конечно могу ошибаться, ибо код для моего мозга достаточно мутный))))) Вобщем я склонен считать что здесь проблема в тесте, а не баг Адоба. Избавьтесь от ректангла, он тут совершенно не нужен, как я показывал в своем первом посте. Заметьте – это было все, что я изменил в вашем коде, и он заработал.
__________________
Reality.getBounds(this);

Старый 03.08.2011, 19:11
Gantenbain вне форума Посмотреть профиль Отправить личное сообщение для Gantenbain Найти все сообщения от Gantenbain
  № 8  
Ответить с цитированием
Gantenbain

Регистрация: Jul 2011
Сообщений: 32
1. Предлагаете оформить ее методом класса? Методы класса, имхо, должны отражать существенные особенности класса, а повторяющиеся вычисления удобно помещать в такие функции (это, конечно, частные особенности стиля - кто-то их и никогда не использует). Мнение о том, что вложенные функции "зло", встречал, но язык предусматривает такой прием, хотя для пользы дела, если вот такой "тупик", то можно и просто внутри кода разместить повторяющиеся операции ("раздует" его, правда ).
2. В системе координат объекта (самого, содержащего каверзную БитмапДату класса) точно такая же картина - пробовал. Дело в том, что координаты Ректангла дают действительное размещение объекта в стейдже, именно там он и выводится, и там его место, но "мутность" в том, что последним описанным мной способом, я пишу в БитмапДату Фигуру из области, в которой ее нет - вот это меня и удивляет.

P.S. Кстати, как "избавиться от Ректангла" - не понимаю. drawPath у меня рисует фигуру, состоящую из многих Безье-кривых, т.е. чтобы получить адреса пикселей, заполняющих фигуру, я этот Ректангл сканирую.


Последний раз редактировалось Gantenbain; 03.08.2011 в 19:18.
Старый 03.08.2011, 20:14
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 9  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Существенные особенности класса отражают его публичные методы. Приватные методы служат нуждам самого класса или его представителя-экземпляра, они инкапсулированы и являются секретом фирмы, так что никаких особенностей отражать не могут – наоборот, являются внутренними методами для операций, нужных данному классу, и только ему. Это чем-то противоречит цели данной функции?
Цитата:
я этот Ректангл сканирую.
Полученный в координатах стейджа, а наложенный на битмапдату. Зачем Вам этот ректангл? Есть же все что нужно - высота и ширина битмапдаты, и адрес ее первого пикселя - (0, 0)?

Добавлено через 3 минуты
Протрейсите ректангл, может я и зря на него наезжаю, но лучше уж знать, с чем имеем дело.
В моем примере с getVector нет вообще никакого ректангла кроме bmpdata.rect - и то лишь потому что его требует метод.
__________________
Reality.getBounds(this);


Последний раз редактировалось Wolsh; 03.08.2011 в 20:23.
Старый 04.08.2011, 10:50
Gantenbain вне форума Посмотреть профиль Отправить личное сообщение для Gantenbain Найти все сообщения от Gantenbain
  № 10  
Ответить с цитированием
Gantenbain

Регистрация: Jul 2011
Сообщений: 32
Цитата:
Это чем-то противоречит цели данной функции?
Нет, но в отсутствие аргументов против использования "внутренних" функций, лишь при наличии мнения, что их использование не есть хорошо, я буду руководствоваться соображениями удобства. Меня убеждают не мнения, а аргументы. В данном случае, не вижу вреда от помещения кода во внутреннюю функцию, удобство, напротив, есть.
Цитата:
Зачем Вам этот ректангл?
Так именно в том и загвоздка, что рисуя в BitmapData, я не нахожу пиксели фигуры в ее адресах! В тех адресах, где она должна по идее размещаться. Посмотрите на левый фрагмент рисунка вставленного в мой предыдущий пост: на нем видно, что, на первом же шаге цикла, квадрат отрисован в BitmapData (bmpdata) с началом не в точке (0, 0), а со смещением в точку, являющуюся начальной точкой его отрисовки - (5, 5) (я размеры битмапдаты специально увеличил сверх размеров фигуры для наглядности, чтобы было видно, что пиксели фигуры смещаются по мере того, как меняется начальная точка ее отрисовки, что я и полагаю багом). Координаты Ректангла позволяют мне следить за этим смещением - это единственное его назначение в данном случае.
Разумеется, строить код на противоречащих концепции языка, или на других приемах, в отношении которых, по любым причинам, испытываешь внутреннее сомнение, плохо. Поэтому, для практических целей, вероятно, стоит поэкспериментировать для начала с другими способами создания графического контента фигуры (я не пробовал старые методы moveTo(), lineTo()),- потому что альтернативы BitmapData нет (ByteArray напрямую из фигуры не создашь, и в нем будут только "кривые" пиксели из битмапдаты).


Последний раз редактировалось Gantenbain; 04.08.2011 в 10:58.
Создать новую тему Ответ Часовой пояс GMT +4, время: 09:26.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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