웹으로 만드는 카메라 앱

15263 단어 iOSPHPPWA라라벨
앞으로 PWA가 iOS에서도 완전히 구현될 것을 기대하고 웹에서 카메라 앱을 만들어 보려고 생각해 보았습니다.

제목



졸작 향수 사진 필터를 웹 앱으로 만듭니다.
벌써 9년 전이군요-그리운.
※앱은 ​​배포를 종료하고 있습니다.



출처



여기 있습니다.
htps : // 기주 b. 코 m / 미우라 333 / s s ぃ l rp 2

개발 환경




품목
내용
비고


서버
롤리팝
고유 도메인 획득, 무료 SSL

언어
PHP7.1

프레임워크
Laravel 5.7.13

DB
사용하지 않고

이미지 처리 라이브러리
GD

검증 터미널
iOS12.0.3, 11.3



롤리포 환경에 Laravel 넣어 동작시키고 있습니다.
전혀 프레임 워크의 장점을 활용하지 못해 죄송합니다.

전제 조건


  • PHP로 작성
  • 서버에 가능한 한 파일을 남기지 마십시오.

    해설



    카메라에서 이미지 획득


  • 카메라이지만, manifest.json의 display가 fullscreen, 또는 meta 태그의 apple-mobile-web-app-capable을 yes로 설정해, 풀 스크린으로 표시시키려고 하면 에러가 되어 카메라 영상을 표시시키는 것 수 없습니다.
  • Safari의 PWA 대응, 보다는 풀 스크린인가 아닌가에 의해서 동작이 하는, 하지 않는 것이 바뀌는 것 같습니다.

  • manifest.json
    {
        "name": "nosfilter-pwa",
        "short_name": "nosFilter",
        "background_color": "#ffffff",
        "icons": [{
            "src": "./icon-152.png",
            "sizes": "152x152",
            "type": "image/png"
        },{
            "src": "./icon-120.png",
            "sizes": "120x120",
            "type": "image/png"
        }],
        "start_url": "./?utm_source=homescreen",
        "display": "browser",
        "theme_color": "#f7f7f7"
    }
    
  • HTML측입니다만, 버튼 누르고 나서 카메라 영상을 canvas에 묘화 해, 그것을 jpeg 형식으로 출력하고 있습니다.
  • 그리기 전에 카메라의 가로세로 크기와 캔버스의 크기를 동일하게 합니다.

  • index.blade.php
    <body class="cameraBody">
        <video id="video" autoplay playsinline></video>
        <div class="cameraSpacer"></div>
        <div class="cameraButtonParent">
            <div class="cameraButtonParent2">
                <input id="btnPicture" type="button" disabled="true" value="OK" class="cameraBtn"></input>
            </div>
        </div>
        <canvas id="imageCanvas" style="display:none;" width="300" height="300"></canvas>
        {!! Form::open(['url' => '/result', 'id' => 'formResult']) !!}
        {!! Form::hidden('imageData', null, ['id' => 'imagePost']) !!}
        {!! Form::close() !!}
    
        <script>
            const medias = {audio : false, video : {
                facingMode : {
                  exact : "environment" // リアカメラにアクセス
                }
            }},
            video  = document.getElementById("video");
    
            navigator.getUserMedia(medias, successCallback, errorCallback);
    
            var width = 0, height = 0;
    
            video.addEventListener( "loadedmetadata", function (e) {
                width = this.videoWidth;
                height = this.videoHeight;
            }, false );
    
            function successCallback(stream) {
                video.srcObject = stream;
    
                var button = document.getElementById("btnPicture");
                var canvas = document.getElementById("imageCanvas");
    
                button.disabled = false;
                button.onclick = function() {
                    canvas.width = width;
                    canvas.height = height;
                    canvas.getContext("2d").drawImage(video, 0, 0, width, height, 0, 0, width, height);
                    var img = canvas.toDataURL("image/jpeg");
    
                    $('#imagePost').val(img);
                    $('#formResult').submit();
                };
            };
    
            function errorCallback(err) {
                alert(err);
            };
        </script>
    </body>
    

    이미지 처리


  • 화상 처리는 Form에서 받은 데이터를 파일 보존, 그 파일을 GD로 읽어들입니다.
  • GD에서 데이터에서 읽는 방법을 모르는 고통의 방법. 결국 파일이 삭제되었습니다.
  • 나머지는 GD를 사용해 픽셀 데이터에 액세스 해 화상 처리의 흐름입니다.

  • 다음은 소스의 일부, 그레이 스케일 화하고 있는 개소의 발췌입니다.

    imageController.php
    
    $img = str_replace('data:image/jpeg;base64,', '', $request->imageData);
    $img = str_replace(' ', '+', $img);
    $data = base64_decode($img);
    $timestamp = time();
    $file = $timestamp . ".jpeg";
    Storage::disk('local')->put('public/'.$file, $data);
    $storagePath = asset('storage/');
    Log::debug($storagePath);
    
    $src = imagecreatefromjpeg('storage/'.$file);
    
    $imageWidth = imagesx($src);
    $imageHeight = imagesy($src);
    
    $grayImage = imagecreatetruecolor($imageWidth, $imageHeight);
    
    for($i = 0; $i < $imageWidth; $i++){
        for($j = 0; $j < $imageHeight; $j++){
            //get pixel
            $rgb = imagecolorat ($src, $i, $j);
            $r = ($rgb >> 16) & 0xFF;
            $g = ($rgb >> 8) & 0xFF;
            $b = $rgb & 0xFF;
    
            $gray = ($r*0.125)+($g*0.25)+($b*0.0625);
            $dstColor = imagecolorallocate($grayImage, $gray, $gray, $gray);
            imagesetpixel($grayImage, $i,$j, $dstColor);
        }
    }
    
    

    이미지 데이터 생성


  • jpeg 이미지를 저장하고 base64 인코딩
  • 선두에 인수로 왔을 때와 같은 헤더를 부여해 View에 건네줍니다. 이 헤더가 없으면 img 태그로 표시되지 않습니다.

  • imageController.php
    imagejpeg($resultImage, 'storage/'.$fileOut, 80);
    
    $dataOut = file_get_contents('storage/'.$fileOut);
    $imageData64 = base64_encode($dataOut);
    
    unlink('storage/'.$fileOut);
    
    return view('result')->with(['imageData' => 'data:image/jpeg;base64,'.$imageData64, 'width' => $imageWidth, 'height' => $imageHeight]);
    

    할 수 있었다



    감상


  • 느린. Wi-fi라면 토끼도 각 4G 회선으로 시험하면 셔터 압하 후의 동작이 매우 무겁습니다.
  • 당초 png로 데이터 취득을 하고 있었습니다만, jpeg로 바꾸어도 체감적으로 그다지 바뀌지 않았습니다.
  • javascript판도 만들어 보려고 생각합니다만, 만일 상용 이용을 생각했을 경우에 javascript라고 화상 처리 부분의 소스를 카피 할 수 버리기 때문에 어떻게 할까.
  • 우선 사진을 촬영해 픽셀 데이터를 만져 필터링할 정도는 할 수 있다는 것을 알았습니다. 사진을 올리기 위해서만 앱을 만들고 싶은 듯한 의뢰가 오면 제안해볼까.
  • 화상 처리 서버는 메모리 소비가 많다.

  • 참고



    htps : // 코 m / 우마 미치 / ms / 0 2b4b1c578 7335 ba 20
    htps : // m / mu_mumo / / ms / d35d b580 a 561c562 또는 6
    h tp // 기미즈카. 하테나 bぉg. 코m/엔트리/2017/11/06/140337

    좋은 웹페이지 즐겨찾기