Как стать автором
Обновить

Сохранение изображения из Adobe Flash Player на диск с помощью MDM Zinc

Время на прочтение7 мин
Количество просмотров669
Здравствуйте, хабралюди.

Небольшая предыстория. У меня все началось с обычного Flash-сайта, максимальный функционал которого, заключался в открытии какого-либо окна с текстом по нажатию какой-либо кнопочки. Затем была первая игра в виде катающегося по полю танка с поворачивающимся дулом, затем первая MMORPG. После этого, там, куда я устроился на работу поняли, что MMORPG — не совсем то, что нужно, и все дружно решили выпускать игры для PC. На дисках, в красивых коробочках, все как положено.

Какой же язык программирования выбрать? Все дружно скандировали: «Си, Си, Си». Все бы хорошо, если бы не одно «НО» (это «но» стало известным непосредственно перед началом работы). Эта же версия игра должна была быть в онлайне, в сайте, зашита в HTML с кучей посетителей (помните как я говорил об отказе от MMORPG? Ага, щаз!). Как подружить файл с расширением .EXE с HTML или PHP никому в голову не пришло. Было решено сделать так: для PC написать всё на ActionScript (тогда еще 2.0), обернуть это оболочкой с помощью компонента для Builder'а, а для веба обернуть SWF-файл HTML-кодом. И всё получилось. Веб-версия нам так и не понадобилась, а полноценная PC-версия игры была написана на ActionScript 2.0. И художникам рисовать удобно, и нам, как flash-программистам — счастье.

Ближе к делу. Эта игра развивалась. На сегодняшний момент выпущено 9 версий, которые успешно продаются и, соответственно, покупаются. С каждой новой версией игры, её функционал увеличивался, и в этот момент мы дружно дошли до ситуации, когда нужно взять текущее изображение персонажа и сохранить его на диск. Вот и приехали. Что может сохранить Flash на диск? — жалкий SharedObject с текстовыми данными. А у нас здесь не до шуток. Тут имеем дело с изображениями. У нужен JPEG и как ни крути, что хочешь, то и делай, но только сохрани мне его. Сначала формировали байтовые массивы, с помощью fscommand пересылали оболочке, оболочка разибирала его, формировала изображение и сохраняла на диск? Удобно? — Естественно нет. Чтобы что-то перенастроить, приходилось в корне менять весь код.

И тут случай натолкнул меня на MDM Zinc от Multidmedia. Замечательный инструмент для создания десктопных приложений как для Windows, так и для Linux и MacOS. Загружаем в него флешку и настольное приложение готово. EXE-шничек, со встроенным Flash Player'ом и огромным функционалом для работы со всеми прелестями Windows. Хоть в реестр лезь, хоть в файловую систему.

Zinc устанавливается элементарно. Вам практически ничего не нужно делать (кроме как установить расширение с помощью extension manager). А простор для мысли открывается огромный. Вот и начал я потихоньку делать ImageSaver (так я его назвал). Решил сначала сделать так. Открываю приложение, выбираем файл с картинкой, загружаем в оболочку, фотографируем нужную часть мувика, сохраняя изображение на диск. Создаем сначала ролик (мувик).

Смотрим что должно быть во Flash-ролике

Пустому клипу загрузчика изображения даём имя (instance name) — mc_loader. Клипу сканнера (голубой прозрачный прямоугольник) даём имя — imageScanner. В качестве параметра Document class у ролика (вкладка properties) указываем Saver. Класс должен лежать в той же папке, что и мувик, и приложение. В библиотеку ролика закинуть компонент Zinc.

Далее напишем код Saver'а:

/**
* @author DaFive
* mailto, gtalk: dafive.get@gmail.com
* icq: 163-092-469
*
* ImageSaver class. Interaction with MDM.Zinc.
*
* */

package {
  
  import flash.display.Loader;
  import flash.display.Sprite;
  import flash.events.MouseEvent;
  import flash.display.MovieClip;
  import flash.net.URLRequest;
  import flash.utils.Timer;
  import flash.events.TimerEvent;
  import flash.events.Event;

  import mdm.*;

  public class Saver extends Sprite
  {
    
    //таймер для скрытия сканнера
    private var TIMER:Timer;
    //время
    private var TIME:int = 0;
    
    //путь до приложения
    var myAppPath:String;
    
    public function Saver():void
    {
        //!!ОБЯЗАТЕЛЬНЫЙ ВЫЗОВ ФУНКЦИИ init для mdm-приложения.
      mdm.Application.init(this, onInit);
    }
    
    //инициализация приложения Zinc
    public function onInit():void
    {
      myAppPath = mdm.Application.path;
      
      //выносим на передний план
      mdm.Application.bringToFront();
      
      //путь к файлу
      var myFilePath:String = mdm.Dialogs.BrowseFile.show();
            
      mdm.Dialogs.prompt(myFilePath);
      
      //загрузка картинки в приложение
      var myLoader:Loader       = new Loader();  
      var requestPhoto:URLRequest   = new URLRequest(myFilePath);    
      
      myLoader.load(requestPhoto);  
      
      mc_loader.addChild(myLoader);  
      
      myLoader.contentLoaderInfo.addEventListener(Event.INIT, initPhoto, false, 0, true);
      
      
      imageScanner.addEventListener(MouseEvent.MOUSE_DOWN, onScannerPress, false, 0, true);
      imageScanner.addEventListener(MouseEvent.MOUSE_UP, onScannerRelease, false, 0, true);
      
      imageScanner.buttonMode = true;
     
      save_btn.addEventListener(MouseEvent.CLICK, onSave, false, 0, true);
    }
    
    //завершение загрузки
    private function initPhoto(e:Event):void
    {
      mdm.Dialogs.prompt ("Загружено");
    }
    
    //сохранение
    private function onSave(e:MouseEvent):void
    {
      save_btn.removeEventListener(MouseEvent.CLICK, onSave);
      
      imageScanner.alpha = 0;
      
      TIMER = new Timer(1000, 0);
      TIMER.start();
      TIMER.addEventListener(TimerEvent.TIMER, onTimer, false, 0, true);
    }
    
    //сохранение изображениея на диск, остановка таймера, разблокировка кнопки
    private function onTimer(e:TimerEvent):void
    {
      TIME ++;
      
      if (TIME == 1)
      {
        var rnd_val:Number = Math.random();
        
        mdm.Image.ScreenCapture.movieAreaToBmp(imageScanner.x, imageScanner.y, imageScanner.width, imageScanner.height, myAppPath+"\\shot_" + rnd_val + ".bmp");
        
        mdm.Image.bmpToJpg(myAppPath+"\\shot_" + rnd_val + ".bmp");
        
        mdm.FileSystem.deleteFile(myAppPath+"\\shot_" + rnd_val + ".bmp");
        
        TIMER.stop();
        TIMER.reset();
        TIMER.removeEventListener(TimerEvent.TIMER, onTimer);
        
        TIME = 0;
        
        save_btn.addEventListener(MouseEvent.CLICK, onSave, false, 0, true);
        
        imageScanner.alpha = 1;
      }
    }
          
    //нажатие на сканнер
    private function onScannerPress(e:MouseEvent):void
    {
      e.currentTarget.startDrag(false);
    }
    
    //отпускание сканнера
    private function onScannerRelease(e:MouseEvent):void
    {
      e.currentTarget.stopDrag();
    }
  }
}


* This source code was highlighted with Source Code Highlighter.


Самое главное — вызвать в конструкторе класса Saver функцию инициализации прииложения MDM. Без неё работать в третьей версии языка ActionScript ничего не будет. Во второй работает, а здесь — нет.

Как видим, нашему сканеру присваивается свойство drag (по нажатию ЛКМ) и свойство drop (при отпускании ЛКМ). То есть мы можем его таскать на нужный кусок изображения. Размер сканнера фиксированный, но вы можете это легко изменить.

По нажатию кнопки «Сохранить» происходит запуск таймера в одну секунду. Ибо если мы сделаем без таймера — сохранится и прозрачный прямоугольник. Его-то мы и скрываем. Дело еще вот в чем. Zinc не умеет сохранять нужный кусок изображения с нужной координаты сразу в JPG. Но уммет сохранять в BMP и конвертировать его в JPG. Это мы и делаем после if (TIME == 1).

Файлу присваивается имя случайным образом (специально сделал, чтобы можно было сохранить несколько вариантов изображения и не перетереть их). Файл будет сохранятся в папке где и лежит само приложение (myAppPath нам поможет). Затем идёт конвертация из BMP в JPG (mdm.Image.bmpToJpg) и последующее удаление BMP-файла за ненадобностью.

Какие расширения Zinc потребуется подключить?

Что получаем при билде проекта?

Как наводим сканер?

Сохраненное изображение

Надеюсь, что кому-нибудь пригодится. Не ругайте, если что. Мой первый топик.
Теги:
Хабы:
+3
Комментарии4

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн