Подтвердить что ты не робот

Схват каждого кадра холста HTML5

Эти изображения цикла палитры захватывают дух: http://www.effectgames.com/demos/canvascycle/?sound=0

Я хотел бы сделать некоторые (или все) из них на фоне рабочего стола.

Я мог бы использовать анимированную версию gif, но я понятия не имею, как получить это из холста "анимация". Есть ли что-нибудь еще, что может сделать что-то в этом направлении (специально для этой ссылки и вообще).

4b9b3361

Ответ 1

У меня есть решение, но оно зависит от того, как вы знакомы с Javascript Console в Firefox (установите Firebug plugin), Chrome или Safari,

Если вы этого не сделаете, перейдите в Google или попробуйте щелкнуть правой кнопкой мыши в любом месте страницы, выберите "Осмотреть элемент" и найдите "Консоль"...

Что делает код:

Он позволяет вам принимать 10 скрин-графов элемента CANVAS каждые 1/10 секунды. Оба эти значения легко изменяются, так как вы можете настроить, чтобы найти количество итераций, которые вы хотели бы получить. Для примера, который вы указываете, идентификатор элемента canvas является "mycanvas".

После того, как у него есть экраны, он выводит изображения на страницу. В этот момент вы можете сохранить отдельные изображения.

Запуск кода

Вставьте следующий код в Javascript Console:

var canvas = document.getElementById("mycanvas");
var shots  = [];
var grabLimit = 10;  // Number of screenshots to take
var grabRate  = 100; // Miliseconds. 500 = half a second

var count     = 0;

function showResults() {
    //console.log(shots);
    for (var i=0; i<shots.length; i++) {
      document.write('<img src="' + shots[i] + '"/>\n');
    }
}

var grabber = setInterval(function(){
  count++;

  if (count>grabLimit) {
    clearInterval(grabber);
    showResults();
  }

  var img     = canvas.toDataURL("image/png");
  shots.push(img);
}, grabRate);

и нажмите CTRL-Enter, чтобы выполнить его.

Это займет несколько секунд, поэтому, пожалуйста, будьте терпеливы.

После этого у вас должны быть все необходимые фреймы (возможно, больше) для создания анимированного GIF через ImageMagick, этот веб-сайт MakeAGif.com, или другое приложение.

Боковое примечание

Если по какой-то причине вам нужно вывести как GIF JPG вместо PNG, просто обновите, если необходимо, следующее:

var img     = canvas.toDataURL("image/png");

к одному из следующих:

var img     = canvas.toDataURL("image/gif");
var img     = canvas.toDataURL("image/jpg");

Поддержка вывода как gif или jpg может быть не во всех браузерах (должна быть больше).

(БОЛЬШОЙ) ОБНОВЛЕНИЕ # 1

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

Во-вторых, этот новый код НЕ РЕШИТ проблему. Это своего рода недостаток. Он создает анимированный GIF (Yipee!), Но его в разных оттенках зеленого (Boooo!). Не знаете, как и почему, но, может быть, кто-то может взять это отсюда и посмотреть, что я пропустил.

Итак, мы идем... применяются те же правила - скопируйте и вставьте его в Javascript Console браузера (он отстает от Firefox, но Google Chrome довольно быстро... 10 секунд или около того).

var jsf  = ["/Demos/b64.js", "LZWEncoder.js", "NeuQuant.js", "GIFEncoder.js"];
var head = document.getElementsByTagName("head")[0];

for (var i=0;i<jsf.length;i++) {
  var newJS = document.createElement('script');
  newJS.type = 'text/javascript';
  newJS.src = 'http://github.com/antimatter15/jsgif/raw/master/' + jsf[i];
  head.appendChild(newJS);
}

// This post was very helpful!
// http://antimatter15.com/wp/2010/07/javascript-to-animated-gif/

var w = setTimeout(function() { // give external JS 1 second of time to load

    console.log('Starting');

    var canvas = document.getElementById("mycanvas");
    var context = canvas.getContext('2d');
    var shots  = [];
    var grabLimit = 10;  // Number of screenshots to take
    var grabRate  = 100; // Miliseconds. 500 = half a second
    var count     = 0;

    function showResults() {
        console.log('Finishing');
        encoder.finish();
        var binary_gif = encoder.stream().getData();
        var data_url = 'data:image/gif;base64,'+encode64(binary_gif);
        document.write('<img src="' +data_url + '"/>\n');
    }

    var encoder = new GIFEncoder();
    encoder.setRepeat(0);  //0  -> loop forever, 1+ -> loop n times then stop
    encoder.setDelay(500); //go to next frame every n milliseconds
    encoder.start();

    var grabber = setInterval(function(){
      console.log('Grabbing '+count);
      count++;

      if (count>grabLimit) {
        clearInterval(grabber);
        showResults();
      }

      var imdata = context.getImageData(0,0,canvas.width,canvas.height);
      encoder.addFrame(context);

    }, grabRate);

}, 1000);

Он использует некоторые полезные коды, указатели и файлы JS, упомянутые в этом сообщении в блоге JavaScript для (анимированных) GIF. Я использую некоторые файлы JS напрямую, но вы должны скопировать их локально, если вы собираетесь использовать его много.

Выход для меня - это GIF: alt text

Итак, это что-то, но не то, что вам нужно...

Ответ 2

РЕДАКТИРОВАТЬ. Наконец, включите этот код, вот результат:

alt text

Imagick сгенерировал большое изображение, поэтому я пошел дальше и оптимизировался с помощью gimp.

Клиентский код - это модифицированная версия кода Майкла:

var canvas = document.getElementById("mycanvas");
var shots  = [];
var grabLimit = 30;  // Number of screenshots to take
var grabRate  = 100; // Miliseconds. 500 = half a second

var count     = 0;

function postResults() {
   console.log("START---------");
   for (var i = 0; i < shots.length; i++) {
      document.write(shots[i]+"<br />");
   }    
   console.log("END-----------");
}

var grabber = setInterval(function(){
  count++;

  if (count>grabLimit) {
    clearInterval(grabber);
    postResults();
  }

  var img     = canvas.toDataURL("image/png");
  shots.push(img.replace("data:image/png;base64,",""));
}, grabRate);

Он напишет кучу строк base64 на экран. Скопируйте их и сохраните в текстовый файл, а затем загрузите на свой веб-сервер. Затем запустите другой script (см. Ниже), и он напишет изображение на ваш веб-сервер. Полученное изображение будет большим и, возможно, прерывистым, поэтому откройте GIMP и оптимизируйте разницу и GIF. При сохранении заставляйте его использовать одну и ту же задержку для всех кадров, чтобы анимация была гладкой.


Не слишком сложно использовать PHP.

  • Возьмите dataURL (base64 encoded string) для каждого фрейма с помощью JS и отправьте его на сервер.
  • Декодируйте строки base64 и преобразуйте их в объекты Imagick.
  • Добавьте эти объекты Imagick в кадры в новый объект Imagick.
  • Сохранить объект Imagick в файловой системе как GIF.

Так как michael уже отправил хорошее решение JS, я добавлю код на стороне сервера, если вы хотите его автоматизировать:

<?php
$imageData = array_map('rtrim', file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)); //base 64 strings separated by newlines
$delay = 100;
$filename = 'coolmoviebro.gif';
$gif = new Imagick();

for($i = 0; $i < count($imageData); $i++) {
   $tempImg = new Imagick();
   $tempImg->readimageblob(base64_decode($imageData[$i]));
   $gif->addImage($tempImg);
}

$gif->setFormat('gif');
$gif->setImageDelay($delay);
$gif->writeImages($filename, true);

?>

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

Ответ 3

Я взглянул на код, и кажется, что это возможно с небольшим взломом.

Изучая список объектов цикла в Palette.Cycles, вы должны уметь определять длину цикла каждого цикла с полями cycle.high, cycle.low и cycle.rate. Тем не менее, вам понадобится другой алгоритм для каждого из шести возможных значений для цикла. Реверс.

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

Затем установите функцию animate в main.js, чтобы взять параметр tickCount и передать это в palette.cycle вместо использования чего-либо, основанного на реальном времени. Увеличьте количество тиков по периоду выборки с каждой итерацией.

Оттуда вы должны иметь возможность модифицировать метод рендеринга класса Bitmap, добавив необходимую логику для копирования холста в файл. Кажется, есть библиотеки, которые могут управлять этим последним битом для вас. Я бы рекомендовал сохранять файлы, используя количество меток в качестве имени файла (с достаточным количеством начальных нулей, чтобы привести их в порядок.) Сшивание всех изображений вместе в анимированный GIF может выполняться как пакетное задание с использованием правильного программного обеспечения.

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

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

Ответ 4

К сожалению, согласно создателю искусства, невозможно преобразовать его в анимацию GIF из-за того, что разные части изображения имеют различные циклы.

Ответ 5

Попробуйте PhantomJS

Этот script сохраняет 100 кадров.

var webPage = require('webpage');
var fs = require('fs');
var page = webPage.create();

var NB_FRAME = 100;
var current = 0;

page.open('http://www.effectgames.com/demos/canvascycle/?sound=0',
function(status) {
  if (status === "success") {
     var current = 0;
     var grabber = setInterval(function () {
      var frame = page.evaluate(function() {
       return document.getElementById('mycanvas').toDataURL("image/png").split(",")[1];
      });
      fs.write("./frame-" + current + ".png",atob(frame), 'wb');
  if (++current === NB_FRAME) {
     window.clearInterval(grabber);
     phantom.exit(0);
  }
   }, 1000);
}
});

Запустите его:

 phantomjs SaveCanvasFrame.js

Затем используйте ImageMagick

convert *.png animated.gif

Здесь мы идем: animated