2013-04-13 3 views
2

사용자가 캔버스에 렌더링 된 이미지를 저장할 수 있도록 시도하고 있습니다. 이미지가 여러 개있을 수 있으며 사용자가 모든 이미지를 한 번에 하나의 tar 파일로 다운로드 할 수 있기를 바랍니다. 이 tar 파일을 생성하는 코드를 작성하려고합니다. 필자는 대부분이 작업을했지만 tar 파일이 내 컴퓨터로 다운로드 될 때 png 파일을 구성하는 일부 바이너리 데이터가 손상되었음을 발견했습니다.유효한 바이트 문자열로 데이터 URL 변환

var canvBuffer = $('<canvas>').attr('width', canvasWidth).attr('height', canvasHeight); 
var ctxBuffer = canvBuffer[0].getContext('2d'); 

imgData.data.set(renderedFrames[0]); 
ctxBuffer.putImageData(imgData,0,0); 

var strURI = canvBuffer[0].toDataURL(); 
var byteString = atob(decodeURIComponent(strURI.substring(strURI.indexOf(',')+1))); 

toTar([byteString]); 

function toTar(files /* array of blobs to convert */){ 
     var tar = ''; 

     for (var i = 0, f = false, chkSumString, totalChkSum, out; i < files.length; i++) { 

      f = files[i]; 
      chkSumString = ''; 

      var content = f; 


      var name = 'p1.png'.padRight('\0', 100); 
      var mode = '0000664'.padRight('\0', 8); 
      var uid = (1000).toString(8).padLeft('0', 7).padRight('\0',8); 
      var gid = (1000).toString(8).padLeft('0', 7).padRight('\0',8); 
      var size = (f.length).toString(8).padLeft('0', 11).padRight('\0',12); 

      var mtime = '12123623701'.padRight('\0', 12); // modification time 
      var chksum = '  '; // enter all spaces to calculate chksum 
      var typeflag = '0'; 
      var linkname = ''.padRight('\0',100); 
      var ustar = 'ustar \0'; 
      var uname = 'chris'.padRight('\0', 32); 
      var gname = 'chris'.padRight('\0', 32); 

      // Construct header with spaces filling in for chksum value 
      chkSumString = (name + mode + uid + gid + size + mtime + chksum + typeflag + linkname + ustar + uname + gname).padRight('\0', 512); 


      // Calculate chksum for header 
      totalChkSum = 0; 
      for (var i = 0, ch; i < chkSumString.length; i++){ 
       ch = chkSumString.charCodeAt(i); 
       totalChkSum += ch; 
      } 

      // reconstruct header plus content with chksum inserted 
      chksum = (totalChkSum).toString(8).padLeft('0', 6) + '\0 '; 
      out = (name + mode + uid + gid + size + mtime + chksum + typeflag + linkname + ustar + uname + gname).padRight('\0', 512); 
      out += content.padRight('\0', (512 + Math.floor(content.length/512) * 512)); // pad out to a multiple of 512 
      out += ''.padRight('\0', 1024); // two 512 blocks to terminate the file 
      tar += out; 
     } 

     var b = new Blob([tar], {'type': 'application/tar'}); 
     window.location.href = window.URL.createObjectURL(b); 

    } 

I 비 렌더링 캔버스 상에 이전에 렌더링 된 프레임을 넣고 Base64 인코딩과 상기 프레임의 인코딩 된 PNG 버전 toDataURL() 메소드를 캔버스를 사용하고 : 여기서 중요한 코드이다. 다음으로 atob을 사용하여 이것을 바이트 문자열로 변환하여 생성하는 tar 파일의 내용에 추가 할 수 있습니다.

파일을 16 진수 편집기에서 볼 때 내 tar 헤더는 정확하지만 png의 내용이 올바르지 않습니다. ASCII 내용은 정상적으로 보이지만 2 진 데이터는 뒤섞여 있습니다.

도움을 주시면 큰 도움이 될 것입니다. 감사. 내가 살펴 보았다 관련 게시물에 대한 링크를 첨부

PS. 그들은 도움이되었지만 아직 내 문제를 완전히 해결하지 못했습니다. 감사.

Convert Data URI to File then append to FormDataData URI to Object URL with createObjectURL in chrome/ff

+0

당신은 http://stackoverflow.com/questions/923885/capture-html-canvas-as-gif-jpg-png-pdf와 같이 'image/png' 매개 변수를 보내려고 했습니까? – akonsu

+0

png가 없기 때문에 제가 가지고 있지 않았습니다. 위에서 언급 한대로 기본값이라고 가정합니다. window.location.href = dataURI; 유효한 png 파일을 저장합니다. 확인차; 그러나, 나는 그것을 시도했다. 불운. 감사. –

+0

'canvas.toDataURL'에 버그가 있고 손상된 이미지를 반환한다는 것을 의미합니까, 아니면 무엇을 의미합니까? 코드를 올바르게 이해하면 첫 번째 행에서 캔버스 요소의 너비와 높이를 설정합니다. 이 작업이 완료되면 캔버스가 지워집니다. – akonsu

답변

0

OK, 나는이 문제를 해결했다. 문제는 toTar의 끝에있는 Blob 생성자입니다. 문자열을 전달하면 blob이 바이너리 대신 UTF-8로 데이터를 처리하기 때문에 대신 배열되지 않은 정수 배열에 arrayBuffer를 전달해야합니다. 아래는 내가 Uint8Array에서 파일을 구축하고 마지막에 변환 할 필요를 제거하는 toTar를 다시 작성해야 내 솔루션

var byteArray = new Uint8Array(tar.length); 
    for (var b = 0; b < tar.length; b++) { 
     byteArray[b] = tar.charCodeAt(b); 
    } 

    var b = new Blob([byteArray.buffer], {'type': 'application/tar'}); 
    window.location.href = window.URL.createObjectURL(b); 

이지만,이 적절하게 내 질문에 대답을 잘하면 다른 사람을 도움이 될 것입니다. 감사.

관련 문제