Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Создание битмапы через функцию (http://www.flasher.ru/forum/showthread.php?t=138601)

TanaTiX 12.04.2010 00:37

Создание битмапы через функцию
 
Объявляю переменную
Код AS3:

private var myBitmapData:BitmapData;

Далее при загрузке изображения в обработчике
Код AS3:

bmdSaver(e.target.content,myBitmapData);

И соответствующая функция
Код AS3:

private function bmdSaver(bm:Bitmap,bmd:BitmapData):void{
        trace(bm,bmd);
}

В дальнейшем в этой функции планируется занести в битмапдату загруженное изображение.
Трэйс при этом выдает:
Код:

[object Bitmap] null
Вопрос в том, почему вместо объекта myBitmapData я получаю null, что влечет за собой невозможность занесения полученного изображения в битмапдату.

Все дело в том, что хочется немного унифицировать этот процесс. Можно было бы попробовать хранить данные в массиве, но это ИМХО не правильный подход, т.к. массив не всегда является оптимальным решением, в моем к примеру случае помимо однородных объектов(исходя из цели, для чего собственно все это и затеял), где допустимо применение массива, есть значительное количество объектов, которые по своей природе уникальны и на сцене будут находиться в единственном числе.

udaaff 12.04.2010 00:46

А где вы задаёте значение переменной myBitmapData?

Zebestov 12.04.2010 00:50

по поводу null =) ну все правильно.
ты ссылку на myBtimapData передал, но она пока ни на какой экземпляр не ссылается — ты ж не сделал myBitmapData = new BitmapData(...) где-то раньше по коду, того и null.

mickfallout 12.04.2010 00:51

я гружу битмапы так:
Код AS3:

package 
{
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.Sprite;
        import flash.display.Loader;
        import flash.events.Event;
 
        public class Main extends Sprite
        {
 
                [Embed(source = "resources.swf", mimeType="application/octet-stream")]//Загружаем файл ресурсов. Содержит описания классов с графикой.
                private var Resources:Class;
                static private var resourcesLoader:Loader = new Loader;
                static public var resourcesLink:Loader;
 
                public function Main():void
                {
                        super();
                        if (stage)
                                init();
                        else
                                addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        resourcesLoader.loadBytes(new Resources());
                        resourcesLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,
                                                                                                    resources_completeHandler);
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function resources_completeHandler(e:Event):void
                {
                        addChild(getBitmap("Chest0100"));
                }
 
                static public function getBitmap(imageName:String, width:int=64, height:int=96):Bitmap
                {
                        return new Bitmap(BitmapData(new (resourcesLoader.content.loaderInfo.applicationDomain.getDefinition(imageName) as Class)(width, height)))
                }
        }
 
 
}


TanaTiX 12.04.2010 01:04

udaaff, перед конструктором класса
Zebestov, я это как бы интуитивно догадываюсь, но не понимаю.
Да, у меня в этой переменной ничего нет, но если я в функции bmdSaver ее создам, а потом обращусь не как к аргументу функции, а как к своей ранее объявленной переменной (т.е. не bmd, а myBitmapData), то в итоге всt равно получу null. Собственно в этом и затык :(
mickfallout, спасибо за код, у меня по нему парочка вопросов:
Что делает new Resources()? Не вижу этой функции. К тому же в хэндлере вы сразу добавляете данные, а мне необходимо что б эти данные хранились, а вытащить на сцену их в нужный именно мне момент времени.
В параметрах функции getBitmap вообще запутался, откуда что, да и в самой функции тоже :(

mickfallout 12.04.2010 01:18

Цитата:

Что делает new Resources()?
как и любое new - создает экземпляр класса(в данном случае класса private var Resources:Class;). собственно в Resources изначально кладется заэмбеденная SWFка
getBitmap можно так расписать =) думаю так понятнее
Код AS3:

static public function getBitmap(imageName:String, width:int=64, height:int=96):Bitmap
{
    //достаем из лоадера определение класса нужной битмапдаты
    var bitmapDatasClass:Class = resourcesLoader.content.loaderInfo.applicationDomain.getDefinition(imageName) as Class;
 
    //создаем экземпляр битмапдаты
    var bitmapData:BitmapData=BitmapData(new bitmapDatasClass(width, height));
 
    //создаем битмапу с нужной битмапдатой
    var bitmap:Bitmap=new Bitmap(bitmapData);
    return bitmap;
}

Добавлено через 5 минут
Цитата:

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

var bitmap:Bitmap= Main.getBitmap("Название_битмапы")


Котяра 12.04.2010 09:55

Цитата:

Сообщение от mickfallout (Сообщение 899732)
в любом месте любого класса Вы можете получить нужную битмапу в любое время(естественно после загрузки):
Код AS3:

var bitmap:Bitmap= Main.getBitmap("Название_битмапы")


У вас по getBitmap - создаётся новая битмпдата.
на Вашем месте я бы при первом вызове помещал битмапдаты в словарь и при последующих вызовах возвращал бы ссылку на неё.
Если нужно удаление - в словаре храните счётчик, который инкрементируется при создании битмапы - уменьшается при удалении. в 0 - вызываем dispose.
такой подход позволяет существенно сократить расходы памяти если используется большое количество одинаковых битмапдат.
У меня есть где-то класс менеджера ресурсов работающий по этому принципу. Найду-выложу.
что-то вроде собственного Сборщика Мусора.
Код AS3:

package ru.k0t0vich 
{
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.utils.Dictionary;
        /**
        * Менеджер битмап
        * @author k0t0vich
        */

        public class BitmapManager
        {
 
                static private  var bmpdDict:Dictionary = new Dictionary();/*BitmapData,Object*/
                static private  var bmpdList:Object = {};
 
                static public  function getBitmap(bitmapdataName:String, resourcesLoader:Loader ):Bitmap
                {
                        var bitmap:Bitmap;
                        var bitmapData:BitmapData;
                        // {bitmapData,counter,name}
                        var obj:Object;
 
                        // находим битмапдату в хэш списке
                        // можно было обойтись только словарём, но тогда-бы пришлось обходить
                        //словарь и выискивать объект по name, что медленнее.
                        bitmapData = bmpdList[bmpdName];
                        if (bitmapData)
                        {
                                obj = bmpdDict[bitmapData];
                                obj.counter++;
                        }
                        else
                        {
                                //достаем из лоадера определение класса нужной битмапдаты
                                var bitmapDatasClass:Class = resourcesLoader.content.loaderInfo.applicationDomain.getDefinition(bitmapdataName) as Class;
                                //создаем экземпляр битмапдаты
                                bitmapData = BitmapData(new bitmapDatasClass(0, 0));
                                // сохраняем в словаре
                                obj = { bitmapData:bitmapData, counter:1, name:bitmapdataName };
                                bmpdDict[bitmapData] = obj;
                                // сохраняем в хэш списке
                                bmpdList[bmpdName] = bitmapData;
                        }
 
 
                        //создаем битмапу с нужной битмапдатой
                        var bitmap = new Bitmap(bitmapData);
                        return bitmap;
                }
 
                static private function disposeBitmap(bitmap:Bitmap):void
                {
                        var bitmapData:BitmapData = bitmap.bitmapData;
                        var obj:Object = bmpdDict[bitmapData];
                        obj.counter--;
                        if (obj.counter <= 0)
                        {
 
                                delete bmpdDict[bitmapData];
                                delete bmpdList[obj.name];
                                bitmapData.dispose();
                        }
                }
 
 
 
        }
 
}

Для эмуляции GC можно не проверять по счётчику (мало ли - забыли вызвать disposeBitmap перед удалением Bitmap), а сохранять битмапы в списке, например в obj {bitmapList} - при вызове очистки проходить по списку битмапов и если все они == null диспозить битмапу и очищать списки..
в какой момент вызывать очистку в кастомном коллекторе - тоже вопрос... Можно наверное как-то следить за использованной памятью и на превышении некоего предела вызывать очистку. Тут главное не зациклить
т.к. очистка может ничего не высвободить, а критерий вызова останется.. Например вызывать проверку по таймеру.

mickfallout 12.04.2010 12:39

Цитата:

У вас по getBitmap - создаётся новая битмпдата.
на Вашем месте я бы при первом вызове помещал битмапдаты в словарь и при последующих вызовах возвращал бы ссылку на неё.
хорошая идея, спасибо. учитывая что удаление баитмапдат мне не нужно - переписал функцию так:
Код AS3:

        static private var bitmapDataObject:Object={};
        static public function getBitmap(imageName:String, width:int=64, height:int=96):Bitmap
        {
            var bitmapData:BitmapData;
            if (bitmapDataObject[imageName + "Width" + width + "Height" + height] != null )
            {
                trace("requested bitmap "+imageName+"("+width+"x"+height+"), give out from bitmapDataObject")
                bitmapData = bitmapDataObject[imageName + "Width" + width + "Height" + height];
            }else {
                trace("requested new bitmap "+imageName+"("+width+"x"+height+"), give out from resourcesLoader")
                var bitmapDatasClass:Class = resourcesLoader.content.loaderInfo.applicationDomain.getDefinition(imageName) as Class;
                bitmapData = BitmapData(new bitmapDatasClass(width, height));
                bitmapDataObject[imageName + "Width" + width + "Height" + height] = bitmapData;
            }
            var bitmap:Bitmap=new Bitmap(bitmapData);
            return bitmap;
        }


Котяра 12.04.2010 12:49

Код AS3:

width:int=64, height:int=96

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

Код AS3:

bitmapData = BitmapData(new bitmapDatasClass(width, height));

аналогично
Код AS3:

bitmapData = BitmapData(new bitmapDatasClass(0,0));


TanaTiX 14.04.2010 00:31

Всем спасибо, буду разбираться
Котяра, на сколько я помню по доке, то мы не можем создать битмапдату с шириной или высотой равной или меньше 0


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

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