end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

tiff.js + jsPDF for javascript で tiff→canvas→pdf変換

以下の tiff_to_pdf()、conv_tiff_arrays2pdf()の通りです。

tiff.js、jsPDFだけでなく、javascriptによるbinary処理の振り返りになります。

参考url

html + javascript

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <style>
    body        {font-family:   "ヒラギノ角ゴ ProN W3", HiraKakuProN-W3,
                                游ゴシック, "Yu Gothic", Meiryo,
                                Verdana, Helvetica, Arial, sans-serif; }
    h1          {font-size      :x-large;
                 padding        :0;
                 margin         :5px;           }
    table       {border-collapse:collapse;      }
    th,td       {border         :1px solid #555;
                 white-space    :nowrap;
                 padding        :0 10px;        }
    th          {font-weight    :normal;
                 background-color:#f0f8ff;      }
    th.zuban    {resize         :horizontal;
                 width          :400px;
                 overflow       :hidden;        }
    tbody textarea{resize       :none;
                   width        :100%;
                   height       :100%;          }
    #thumb_nails{margin         :10px;          }
    .pdf_basename{width         :250px          }
  </style>
</head>
<body>
  <h1>SCAN TIFF IMAGE → PDF</h1>
  「download」ボタンをクリックし、少々、お待ちください
  <table>
    <thead>
      <tr>
        <th>PDFファイル名</th><th class="zuban">図番</th><th></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          <input type="text" class="pdf_basename" value="○○○マニュアル">.pdf
        </td>
        <td><textarea>HOGE</textarea></td>
        <td><button type="button">download</button></td>
      </tr>
      <tr>
        <td>
          <input type="text" class="pdf_basename" value="△△△マニュアル">.pdf
        </td>
        <td><textarea>ZUMEN1 ZUMEN2 ZUMEN3</textarea></td>
        <td><button type="button">download</button></td>
      </tr>
    </tbody>
  </table>
  <div id="thumb_nails"></div>
  
  <!-- https://github.com/seikichi/tiff.js -->
  <script src="tiff.min.js"></script>
  <!-- https://github.com/parallax/jsPDF -->
  <script src="jspdf.umd.min.js" ></script>
  <script>
    "strict";
    const req_url_base = "http://192.168.56.114:8080/scan/zumens_2.dat";

    let btn_elms = document.getElementsByTagName("button");
    for (let btn_elm of btn_elms) {
        btn_elm.addEventListener("click",(e)=>{ tiff_to_pdf(e.target) });
    }
    
    const tiff_to_pdf=(btn_elm)=>{
        let tr_elm = btn_elm.parentNode.parentNode;
        let pdf_basename = tr_elm.children[0].children[0].value.trim();
        pdf_basename = pdf_basename.replace(/[\s\/\\\.\?]/g,"_");
        
        let zumens_str = tr_elm.children[1].children[0].value.trim();
        let req_url = req_url_base + "?" +
            zumens_str.replace(/\s+/g, ",").toUpperCase();
        
        fetch(req_url,{method:"GET", cache:"no-cache"})
            .then((res)=>{
                if(!res.ok){
                    throw new Error(`${res.status} ${res.statusText}`);
                }
                return res.arrayBuffer();
            })
            .then((org_array)=>{
                let tiff_arrays = parse_scan_res( org_array );
                
                let div_elm = document.querySelector("#thumb_nails");
                div_elm.innerHTML = "";
        
                conv_tiff_arrays2pdf(tiff_arrays,pdf_basename,div_elm);
            })
            .catch((reason)=>{ alert(reason); });
    }

    const conv_tiff_arrays2pdf=(tiff_arrays,pdf_basename,div_elm)=>{
        let pdf = new jspdf.jsPDF("landscape","mm","a4"); //A4横
        let i = 0;
        for(let tiff_array of tiff_arrays){
            i++;
            let uint8array = Uint8Array.from(tiff_array);
            let tiff = new Tiff({buffer:uint8array.buffer});
            let canvas = tiff.toCanvas();                       //tiff→canvas
            if(i>1) pdf.addPage();                              //pdf page追加
            pdf.addImage(canvas.toDataURL(),"PNG",0,0,297,210); //canvas→pdf
            
            let img_elm = document.createElement("img");        //thumb nail表示
            img_elm.src = canvas.toDataURL();
            img_elm.width  = String(canvas.width / 10);
            img_elm.height = String(canvas.height/ 10);
            div_elm.append(img_elm);
        }
        pdf.save(pdf_basename+".pdf");
    }
    const parse_scan_res=(org_array)=>{
        ret_tiff_arrays = [];
        tmp_img_head = [];
        tmp_img_body = [];
        img_body_size = 0;
        
        org_array = new Uint8Array(org_array);
        let part = "ATR";
        for(let tmp_byte of org_array ) {
            if(part=="ATR"){
                if(tmp_byte==10) part="IMG_HEAD";
                continue;
            }
            if(part=="IMG_HEAD"){
                if(tmp_byte != 10){
                    tmp_img_head.push(tmp_byte);
                    continue;
                }
                let img_head =
                    String.fromCharCode.apply(
                        "",new Uint16Array(tmp_img_head));
                
                img_body_size = parseInt( img_head.split(" ")[2] );
                tmp_img_head = [];
                part="IMG_BODY";
                continue;
            }
            if(part=="IMG_BODY"){
                if(tmp_img_body.length < img_body_size){
                    tmp_img_body.push(tmp_byte);
                    continue;
                }
                ret_tiff_arrays.push( Array.from(tmp_img_body) );
                tmp_img_body = [];
                part = "ATR";
            }
        }
        return ret_tiff_arrays;
    }
  </script>
</body>
</html>