TOP > カテゴリ > JavaScript >

indexedDBのデータベースに画像を保存する[HTML5新機能]

HTML5の新機能である「indexedDB」のデータベースに画像を保存する方法です。画像ということで、Canvasや画像のスキャンラインも操作していますので、画像処理をある程度知っている方でないと、少し難しいかも知れないです。

一部のブラウザの仕様では、サーバーにHTMLファイルをアップしないと、正常に動作しない場合がありますのでご了承ください。

事前準備

このサンプルではPromiseオブジェクトという新機能を使用しています。

Chrome/FireFoxなどは標準で使用可能ですが、IEは未対応ですので、互換性があるMITライセンスの「npo.src.js」(8.7KB)を各自でダウンロードして下さい。

※Promiseの詳細に関してはPromiseを使用して複数のファイルを連続して読み込む[IE対応版]の記事をご覧ください。また、indexedDBオブジェクトはPromiseを使用しなくても動作可能です。

indexedDBの確認方法

indexedDBなどのストレージをブラウザで確認するにはF12キーを押して開発者ツールを起動させます。

Chromeの場合は、Applicationを選択すると表示される「Storage」にIndexedDBがあります。

FireFoxは「ストレージインスペクタ」の「IndexedDB DB」です。

IE/Edgeはわかりません。探せばあるかも知れません。

動作確認

・ Internet Explorer 11(32bit/64bit)
・ Microsoft Edge(32bit)
・ Chrome / FireFoxの最新版
※タブレット、スマートフォンやその他のブラウザは未確認です。

使い方

最初に画像ファイルを読み込みます。次に「indexedDBへ画像を保存する」ボタンを押すと、画像がindexedDBのデータベースに保存されます。

その後、自動的にデータベースから画像を読み取って画像の色を反転させてCanvasに描画します。

サンプルコード

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="npo.src.js"></script> <!-- IEの場合は必要 -->
<script>
 
// キャンバス
var dst_canvas,dst_ctx;   
// イメージ
var image;  

// 非同期でファイルを読み込む
function getAsynchroFile(file) {  
 
  return new Promise(function(resolve, reject) {
    
    var reader = new FileReader();   
    reader.onload = function (event) {   
       resolve(new Uint8Array(reader.result));       
    }
    
    reader.onerror = function (event) {   
       reject('ファイルの読み込みに失敗しました');       
    }
    
    reader.readAsArrayBuffer(file);     
   });
}
  
window.onload = function () {  
  dst_canvas = document.getElementById("SrcCanvas");
  dst_ctx = dst_canvas.getContext("2d");    

  image = document.getElementById("img_source");     
}
 
function OnClick(){
  
  // IndexedDB関連のオブジェクト
  var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB;
  
  // データベースのバージョン
  // ※データベースの構造を後から変更する際に数値を増やして使用する
  var dbVersion = 1; 

  // データベースの生成/読み込み、IDBOpenDBRequestオブジェクトを返す 
  var request = indexedDB.open("petitmonte", dbVersion); 
  
  // DB接続エラー
  request.onerror = function (event) {
    alert("IndexedDB データベースに接続できませんでした。");
  };
  
  // DB接続成功
  request.onsuccess = function (event) {
     
    // IDBDatabase
    var db = request.result;
    
    db.onerror = function (event) {
      alert("IndexedDB データベース接続後にエラーが発生しました。");
    };
    
    // キャンバスの画像データ(RAW)を取得する
    var width  = dst_canvas.width;        
    var height = dst_canvas.height;
    
    var src = (dst_ctx.getImageData(0,0,width, height)).data;  
    var stream = new Uint8Array(width * height * 3);
    
    var sRow,sCol,dRow,count = 0; 
    for (var y = 0; y < height; y++) {
      sRow = dRow= (y * width * 4);               
      for (var x = 0;x < width; x++) {
        sCol = sRow + (x * 4);
        stream[count++] = src[sCol]; 
        stream[count++] = src[sCol + 1];
        stream[count++] = src[sCol + 2];   
      }
    }
    
    // IDBTransaction(読み書き可能なトランザクションを開く)
    var transaction = db.transaction(["Imagelst"], "readwrite");

    // データベースにRAWデータを上書き登録する
    var put = transaction.objectStore("Imagelst").put(new Blob([stream]), "raw");
                                                                          
    // データベースからRAWデータを取得する
    transaction.objectStore("Imagelst").get("raw").onsuccess = function (event) {   
        var file = event.target.result;

        // ファイル(RAWデータ)の読み込み
        getAsynchroFile(file).then(function(raw){
          var width  = dst_canvas.width;        
          var height = dst_canvas.height;
          
          var imagedata = dst_ctx.createImageData(width, height); 
          var dst = imagedata.data;
          
          // わかりやすいように、色を反転させてます。
          var sRow,dRow,dCol,count = 0; 
          for (var y = 0; y < height; y++) {
            sRow = dRow= (y * width * 4);               
            for (var x = 0;x < width; x++) {
              dCol = sRow + (x * 4);                        
              dst[dCol]     = 255 - raw[count++]; 
              dst[dCol + 1] = 255 - raw[count++];
              dst[dCol + 2] = 255 - raw[count++];   
              dst[dCol + 3] = 255;   
            }
          }           
          dst_ctx.putImageData(imagedata,0,0);                
        
        // 読み込みエラー
        }).catch(function(err){
           alert(err);  
        });
    };    
  }
  
  // データベースの新規作成 or アップグレードが必要な場合
  request.onupgradeneeded = function (event) {
    var db = event.target.result; // IDBDatabase 
    
    // オブジェクトストアの生成
    db.createObjectStore("Imagelst");
  }
}
 
function onDragOver(event){ 
  event.preventDefault(); 
} 
  
function onDrop(event){
  onAddFile(event);
  event.preventDefault(); 
}  
 
// ユーザーによりファイルが追加された  
function onAddFile(event) {
  var files;
  var reader = new FileReader();
  
  if(event.target.files){
    files = event.target.files;
  }else{ 
    files = event.dataTransfer.files;   
  }    
 
  // ファイルが読み込まれた
  reader.onload = function (event) {
    
    // イメージが読み込まれた
    image.onload = function (){
      dst_canvas.width  = image.width;
      dst_canvas.height = image.height;
        
      // キャンバスに画像を描画
      dst_ctx.drawImage(image,0,0);  
    };      
       
    // イメージが読み込めない
    image.onerror  = function (){
      alert('このファイルは読み込めません。');  
    };
 
    image.src = reader.result;       
  };
  
  if (files[0]){    
    reader.readAsDataURL(files[0]); 
    document.getElementById("inputfile").value = '';
  } 
}         
</script>
</head>
<body ondrop="onDrop(event);" ondragover="onDragOver(event);" style="background:#ddd;">
  <input type="file" id="inputfile" accept="image/jpeg,image/png,image/gif,image/bmp,image/x-icon" onchange="onAddFile(event);">
  <button onclick="OnClick();">indexedDBへ画像を保存する</button>
  <img id="img_source" style="display:none;">
  <p></p>
  <canvas id="SrcCanvas"></canvas>
</body>
</html>

データベースやデータの削除

データベース、データ(レコード)の削除は次のようにします。

  // データベースの削除
  //indexedDB.deleteDatabase('ここにデータベース名を入力');
  
  // データの削除(1レコード)
  // transaction.objectStore("Imagelst").delete('レコード名');
    
  // 全てのデータの削除(全レコード)
  // transaction.objectStore("Imagelst").clear();  

リンク

IndexedDB (MDN)
IndexedDB に画像とファイルを格納する





関連記事



公開日:2016年11月22日
記事NO:02214