Есть ли способ использовать изображение холста в качестве данных для ввода с типом, равным данным вместо файла? - PullRequest
0 голосов
/ 16 мая 2019

Из формы:

<label for="avatar_file">Select an avatar image:</label>
<input type="file" accept="image/*" id = "avatar_file" name="avatar_file" />
<input type="hidden" name="MAX_FILE_SIZE" value="5000000" />
<input type="submit" value="Upload image" />

Код для подключения веб-камеры к браузеру, сделайте захват видео:

<video id="player" controls autoplay></video>
<button id="capture">Capture</button>
<canvas id="canvas" width=320 height=240></canvas>


<script>
  const player = document.getElementById('player');
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const captureButton = document.getElementById('capture');

  const constraints = {
    video: true,
  };

  captureButton.addEventListener('click', () => {
    // Draw the video frame to the canvas.
    context.drawImage(player, 0, 0, canvas.width, canvas.height);
    //     player.srcObject.getVideoTracks().forEach(track => track.stop());
    var image = new Image();
    image.src = canvas.toDataURL("image/png");
    ????

  });

  // Attach the video stream to the video element and autoplay.
  navigator.mediaDevices.getUserMedia(constraints)
    .then((stream) => {
      player.srcObject = stream;
    });
</script>

Кажется, в основном работает. После включения видео с камеры через браузер, показ видео и захват помещают снимок на холст, но я также хотел бы иметь возможность использовать изображение холста. Я положил ???? туда, где я хотел бы каким-то образом заменить захваченное изображение для источника файла во вводе с помощью type = "file", если это возможно программно, без сохранения захваченного изображения на диск.

1 Ответ

0 голосов
/ 16 мая 2019

Я немного потрудился, и кажется, что самый простой способ - либо позволить пользователю выбрать локальный файл, либо использовать захваченное изображение в POST как тип данных, закодированный в Base64, а затем на странице сервера определить,или не был опубликован файл, если было опубликовано закодированное изображение в кодировке Base64.Я добавляю больше кода, который у меня есть.

    <form id="uploadavatar" class = "ajaxpostform" data-target ="/user/uploadAvatar_action" method="post" enctype="multipart/form-data">
            <label for="avatar_file">Select an avatar image from your hard-disk (will be scaled to 256 x 256 px, only .jpg currently):</label>
            <input type="file" accept="image/*" id = "avatar_file" name="avatar_file" />
            <!-- max size 5 MB (as many people directly upload high res pictures from their digital cameras) -->
            <input type="hidden" name="MAX_FILE_SIZE" value="5000000" />
            <input type="submit" value="Upload image" />
        </form>
    </div>

    <div class="box">
        <h3>Delete your avatar</h3>
        <p>Click this link to delete your (local) avatar: <a id="deleteavatar" class = "ajaxload" data-target = "/user/deleteAvatar_action" href="/user/deleteAvatar_action">Delete your avatar</a>
        <video id="player" controls autoplay></video>
        <button id="capture">Capture</button>
        <button id="savecapture" style="display:none;">Save</button>
        <canvas id="canvas" width=320 height=240></canvas>
    </div>

</div>
<?php // echo Config::get('URL'); ?>

<script>
  const player = document.getElementById('player');
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const captureButton = document.getElementById('capture');

  const constraints = {
    video: true,
  };

  captureButton.addEventListener('click', () => {
    // Draw the video frame to the canvas.
    context.drawImage(player, 0, 0, canvas.width, canvas.height);
    // player.srcObject.getVideoTracks().forEach(track => track.stop());
    var image = new Image();
    image.src = canvas.toDataURL("image/png");
    $("#savecapture").show();

        $("#savecapture").on("click", function(e) {
            $.ajax({
                type: "POST",
                url: "/user/uploadAvatar_action",
                dataType: "html",
                data: {
                 imgBase64: image.src }
            }).done(function(data, textStatus, jqXHR) {

                $(".ajaxdata").html(data);

            }).fail(function( jqXHR, textStatus, errorThrown) {

            });
        });
});
  // Attach the video stream to the video element and autoplay.
  navigator.mediaDevices.getUserMedia(constraints)
    .then((stream) => {
      player.srcObject = stream;
});
</script>

На стороне сервера есть некоторый код, который изначально был написан только для отправки файла.Немного изменил его, чтобы при отправке закодированного изображения Base64 он вызывал функцию generateImage, которая записывает декодированное изображение Base64 в файл temp.png в папке avatars, а затем просто возвращает его в функцию createAvatar.Я использую фреймворк "Огромный" на Github, поэтому я делаю некоторые изменения.Не совсем уверен, как определить, является ли изображение .png, .jpg, .gif и т. Д., Но, похоже, оно работает с веб-камерой Mac.

"Огромный" Framework

public static function createAvatar()
{
    // check avatar folder writing rights, check if upload fits all rules
    if (self::isAvatarFolderWritable() AND self::validateImageFile()) {

        if (isset($_POST['imgBase64'])) {

            $image = self::generateImage($_POST['imgBase64']);
        }

        else {
            $image = $_FILES['avatar_file']['tmp_name'];
        }

        // create a jpg file in the avatar folder, write marker to database
        $target_file_path = Config::get('PATH_AVATARS') . Session::get('user_id');
        self::resizeAvatarImage($image, $target_file_path, Config::get('AVATAR_SIZE'), Config::get('AVATAR_SIZE'));
        self::writeAvatarToDatabase(Session::get('user_id'));
        Session::set('user_avatar_file', self::getPublicUserAvatarFilePathByUserId(Session::get('user_id')));
        Session::add('feedback_positive', Text::get('FEEDBACK_AVATAR_UPLOAD_SUCCESSFUL'));


    }
}

    public static function generateImage($img)

{
    $folderPath = Config::get('PATH_AVATARS');
    $image_parts = explode(";base64,", $img);
    $image_type_aux = explode("image/", $image_parts[0]);
    $image_type = $image_type_aux[1];
    $image_base64 = base64_decode($image_parts[1]);
    $file = $folderPath . 'temp.png';
    file_put_contents($file, $image_base64);
    return $file;
}
...