1

ノート:

ご容赦ください。これは、ペイント/描画シナリオでの取り消しについて尋ねる数十の質問の複製ではありません。

バックグラウンド:

Processing for Android を使用して画像処理アプリケーションを開発してきましたが、今は単純なワンステップの取り消し/やり直し機能を実装しようとしています。

私の最初の (元に戻すのに適した) アイデアは、ダウンサンプリングされたプレビュー画像のみに調整を適用し、一連の調整アクションを保持して、保存時に元の画像に適用することでした。次の 2 つの理由から、このアイデアを破棄する必要がありました。

  • 一部のアクションは完了するまでに数秒かかります。これらのアクションがいくつかあると、すでに遅い保存プロセスが退屈なほど遅くなります。

  • 一部のアクション (カラー ノイズ リダクションなど) は、フルサイズの画像ではなくダウンサンプリングされた画像に適用すると、大幅に異なる (間違った) 結果が生成されます。とにかく、これはそれほど深刻な問題ではありません...

そこで、前後の画像を保存することにしました。

問題:

残念ながら、メモリの制限により、画像をメモリにバッファリングすることはできません。私が現在行っているのは、前後の画像を内部ストレージに保存することです。

しかし、それはパフォーマンス/品質のジレンマを生み出します:

  • jpegは高速です (つまり、私の Xperia Arc S で保存するのに約 500 ミリ秒) が、2 回または 3 回の繰り返しの後、許容範囲を超えて品質が低下します。

  • pngはもちろんロスレスですが、非常に遅い (保存するのに約 7000 ミリ秒) ため、実用的ではありません。

  • bmpおそらく速いと思いますが、Androidはbmpをエンコードしません(Androidの処理は「file.bmp」をtiffとして保存すると思います)。

  • tiffのパフォーマンスは許容範囲内ですが (保存に約 1500 ミリ秒)、Android は tiff をデコードしません。

  • また、この関数を使用して生のピクセル配列をファイルに書き込もうとしました:

    void writeData(String filename, int[] data) {
      try {
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(openFileOutput(filename, Context.MODE_PRIVATE)));
        for (int i = 0; i < data.length; i++) {
          dos.writeInt(data[i]);
        }
        dos.close();
      }
      catch (IOException e) {
        e.printStackTrace();
      }
    }
    

    しかし、完了するまでに2000ms以上かかるので、今のところあきらめました。

質問:

  1. この目的のためにデータを読み書きするより速い方法はありますか?

  2. ...または、最初のアイデアに戻って、その問題を可能な限り解決する必要がありますか?

  3. 他の提案はありますか?

アップデート:

生データを書き込むこの方法を思いつきました:

void saveRAW2(String filename) {
  byte[] bytes = new byte[orig.pixels.length*3];
  orig.loadPixels(); //orig = my original PImage, duh!
  int index = 0;
  for (int i = 0; i < bytes.length; i++) {
    bytes[i++] = (byte)((orig.pixels[index] >> 16) & 0xff);
    bytes[i++] = (byte)((orig.pixels[index] >> 8) & 0xff);
    bytes[i] = (byte)((orig.pixels[index]) & 0xff);
    index++;
  }
  saveBytes(filename, bytes);
}

...そして、完了するまでに 1000 ミリ秒もかかりません。

SD カードにファイルを書き込む場合よりも 3 倍高速に実行されますが、すべての電話で同じであるとは考えられません。右?

とにかく、私はこのメソッドを使用して、保存されたデータを orig.pixels に読み戻しています。

void loadRAW(String filename) {
  byte[] bytes = loadBytes(filename);
  int index = 0;
  int count = bytes.length/3;
  for (int i = 0; i<count; i++) {
    orig.pixels[i] = 
      0xFF000000 |
      (bytes[index++] & 0xff) << 16 |
      (bytes[index++] & 0xff) << 8 |
      (bytes[index++] & 0xff);
  }
  orig.updatePixels();
}

これが完了するまでに最大 1500 ミリ秒かかります。それを最適化するためのアイデアはありますか?

4

1 に答える 1

0

Android の「スクラッチ ディスク」領域が何であるかを調べ、画像をタイルとして処理し、そのスクラッチ ディスクにキャッシュすることをお勧めします。これは、メモリを直接使用するよりも少し遅くなる可能性がありますが、メモリの制限に遭遇することなく画像編集を行うことができ、(Android の SDK に適切な API がある場合)、タイルを完全なファイルに書き込むのに信じられないほど時間がかかることはありません。 . そうは言っても、あなたは「処理」からプレーンな Java に移行したので、質問はもはや処理に関するものではありません...そして私の答えは、おそらく Android SDK に精通している人ほど良くないでしょう。

于 2013-04-04T20:04:18.833 に答える