ГлавнаяПо делу › Скриншот флеш клипа нарисованного на основе динамических данных и сохранение картинки в формате PNG на сервер.

Скриншот флеш клипа нарисованного на основе динамических данных и сохранение картинки в формате PNG на сервер.

November 23rd, 2005

Как то давным-давно, когда flash был еще шестым или пятым, меня наняли делать кучу графиков для отображения статистических данных. Естественно делать начали все на flash. И графиков этих было не меряно, так же карт с разбивкой на области и регионы, столбцы, диаграммы, пироги итд… и казалось конца и карая этому не будет никогда. Но все же как как веревочке не виться а конец будет. Дело шло легко, получалось красиво и клиент был весьма рад прикольным фишкам. И вот когда вся работа уже была сделана и уплачено денег, клиент говорит:
— Погодите? А что это все такое? Как картинку то в word сохранить?
— Вы куда это кнопку “Сохранить картинку как…” дели??!!
Вот так и погибла куча работы, повстречав в конечном итоге собачий хвост а не конечного пользователя.
Потребность в этом была давно, но решение нашлось только с появлением ActionScript 3.

И вот недавно Tinic Uro написал небольшой скрипт для PNG компрпессии BitmapData. Сие стало возможно благодаря новым возможностям ActionScript 3.

Перед тем как вникать в процедуру снятия скриншота с flash клипа и последующего сохранения картинки на сервере, советую ознакомится с новыми классами которые мы будим использовать:

Class ByteArray
Class BitmapData
Class URLRequest
Class URLRequestHeader

Для получения PNG картинки нам понадобится:
      1. Adobe Flash 9 Public Alpha (или же Flash 9 и выше если такой будет существовать на момент прочтения этого текста).
      2. Файл package PNGEnc (с сайта автора не брать, в нем присутствуют ошибки).
      3. Сервер с поддержкой PHP. Или же локальный компьютер, лишь бы на нем исполнялись PHP файлы.
      4. Немного любопытства и 15 минут времени.

Рабочий вариант swf файла предоставлен ниже.
Для того что бы протестировать работу скрипта: нажмите и таскайте мышкой в области ограниченной темно-синей рамкой. После того как результат рисования покажется вам приемлимым, нажмите кнопку “Send img”. Это откроет новое окно в котором отобразится результат (PNG картинка). Для того что бы очистить нарисованное, нажмите кнопку “Clear”. Хуйню просьба не рисовать, подходить к делу без дерзкого фанатизма.

SWF файл


Перегрузите окно браузера и вы увидите свою картинку ниже: Ваши художества и мой аватар из ЖЖ справа. (все по честному, передаем не координаты точек а полную картинку)

Готовая PNG картинка


Итак. Из чего же состоит поцесс генерации картинки на сервере.
PNG картинку генерирует сам flash. Да! Все правильно написано, пакуя заголовки и записывая бинарные данные в массив. На сервер мы передаем готовую картинку в формате PNG.
Пошагово это выглядит так:
      1. Получение BitmapData с MovieClip.
      2. Компрессия BitmapData в PNG при помоши PNGEnc (запись даных в ByteArray).
      3. Передача на сервер ByteArray с помощью URLRequest.
      4. Запись полученных данных в файл на сервере. С помощью PHP скрипта.
      5. :) || :( (в зависимости от личной кармы).

Итак глянем в код.

Код: Action Script

import flash.display.*;
import flash.net.URLRequest;
import flash.net.URLVariables;
//Создаем BitmapData из нашего клипа. Именно с BitmapData работает PNGEnc
// кодируем ее в PNG картинку и отправляем на сервер.
function sendImage(event:Event){
        var data_bmp:BitmapData = new BitmapData(avatar_mc.width,avatar_mc.height);
        data_bmp.draw(avatar_mc);
        var png_image_data:ByteArray = PNGEnc.encode(data_bmp);
        // png_image_data - это и есть наша картинка
        var url_req:URLRequest = new URLRequest("http://127.0.0.1/img_create.php");
        url_req.data = png_image_data; // назначаем объект который будем передавать на сервер 
        url_req.method = URLRequestMethod.POST;
        var rhArray:Array = new Array(new URLRequestHeader("file_name", "my_avatar.png"));
        url_req.requestHeaders = rhArray; // добавляем в заголовок имя файла под которым мы сохраним картинку (как сделать по дуругому так и не придумал...) 
        url_req.contentType = 'application/octet-stream';
        flash.net.navigateToURL(url_req, "_blank");// отправляем на сервер и открываем результат в новом окне. 
}
// Создаем графику в которой будем рисовать. К делу это не относится.
var child:Shape = new Shape();
avatar_mc.addChild(child);

// Подключаем кнопки для прослушивания событий

avatar_mc.addEventListener(MouseEvent.MOUSE_DOWN, onMousedown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseup);
clear_mc.addEventListener(MouseEvent.CLICK, clickHandler);
send_mc.addEventListener(MouseEvent.CLICK, sendImage);
// Код ниже никакого отнощения к сохранению картинки не имеет. 
//Тоесть к делу не относится. Просто рисует линии. Может быть что угодно.
//Главное обеспечить наглядность и унимальность контента, который передаем на сервер.
function onMousedown(event:MouseEvent):void { var to_x = event.localX; var to_y = event.localY; child.graphics.lineStyle(1, 0x192746, 100, true, "normal", "none"); child.graphics.moveTo(to_x,to_y) avatar_mc.addEventListener(Event.ENTER_FRAME, enterFrameHandler); } function onMouseup(event:MouseEvent):void { avatar_mc.removeEventListener("enterFrame", enterFrameHandler); } function enterFrameHandler(event:Event):void { var m_x:Number = avatar_mc.mouseX; var m_y:Number = avatar_mc.mouseY; if((m_x>5 && m_x<290) && (m_y>5 && m_y<75)){ child.graphics.lineTo(avatar_mc.mouseX, avatar_mc.mouseY) } } function clickHandler(event:MouseEvent):void { child.graphics.clear(); }

Код: PHP файл

PHP код взят непосредственно из мануала а именно той части где описано как fwrite работает. Некоторые вещи остались для меня загадкой, но главное что работает.
Код простой и незатейливый. Дополнительных пояснений будим думать не требующий.
<?php

$image_data = $HTTP_RAW_POST_DATA;

$filename_to_save = $HTTP_SERVER_VARS[‘HTTP_FILE_NAME’];

if(isset($image_data) && isset($filename_to_save)){
        $png_file = fopen($filename_to_save, “w”) or die(“File not opened!”);
        if($png_file){
                  set_file_buffer($png_file, 20);
                  fwrite($png_file, $image_data);

                  fclose($png_file);
                  echo(“<img src=”.$filename_to_save.“>”);
        }
}

?>

Файлы для скачиваения

Файлы можно скачать по этой ссылке (обновлено для Flash CS3). Архив содержит:
PNGEncoder – package для пакования BitmapData в ByteArray.
img_create.php- PHP файл для записи картинки.
png_enc_CS3.fla – исходный файл flash

NOTA BENE: не забудте поменять URL в строке var url_req:URLRequest = new URLRequest("http://127.0.0.1/img_create.php"); на соответствующий вашим нуждам.

Категория: По делу

Смотрите также

Класс FontMaestro: Загрузка и применение шрифтов из внешних SWF файлов-библиотек.
  1. April 16th, 2009 at 13:00 | #1

    Ставьте права 777 на папку с картинками что бы записывалось.

  2. Alexsander
    March 27th, 2010 at 09:50 | #2

    А где скачать Adobe_Flash_9_Public_Alpha?

  3. March 29th, 2010 at 10:41 | #3

    Alexsander :
    А где скачать Adobe_Flash_9_Public_Alpha?

    12го Апреля выходит CS5 c 11м флешем :)
    Информация устарела.

  4. Влад
    June 26th, 2010 at 15:44 | #4

    У меня не работает!

  5. June 29th, 2010 at 09:25 | #5

    @Влад
    Отличный комментарий? Что именно не работает? Мржет комп в розетку не включен ;) ?

  6. Roma
    October 28th, 2010 at 19:51 | #6

    Привет, ты передаешь имя файла в этой строчке:
    var rhArray:Array = new Array(new URLRequestHeader(“file_name”, “my_avatar.png”));
    url_req.requestHeaders = rhArray;
    принимаешь так:$filename_to_save = $HTTP_SERVER_VARS['HTTP_FILE_NAME'];
    у меня не пришло имя файла.
    скачал исходник а там в php файле написано так:
    $filename_to_save = “my_avatar.png”;
    Спрашивается что за развод?

  1. Пока нету.