2016-04-17 4 views
0

私は与えられた画像にフィルタを適用できるはずの単純な画像処理ツールを開発中です。私はラムダ式とストリームで機能的な方法でこれをどのように解決するのだろうと思っていました。Javaストリーム - プロセスのrgb値

私は、argb値を持つArrayListとしてカーネルを返すメソッドを記述しました。このメソッドは、どのフィルタを適用するかによってさらに処理できます。たとえば、ボックスフィルタを適用する場合は、すべての要素を合計し、要素数で除算する必要があります。もちろん、私はこれをすべてのrgb値で個別に行う必要があります。

私は以下のように値を取得するために使用:

// Get rgb values: 
    r = (argb >> 16) & 0xff; 
    g = (argb >> 8) & 0xff; 
    b = argb & 0xff; 
// Write back to argb: 
    argb = (0xFF << 24) | (r << 16) | (g << 8) | b; 

しかし、私はストリームでこれを書くでしょうか、何をここに挿入することは値を分割し、独立してそれらを処理し、結果を置く方法を確認していません一緒に戻る

IntStream.range(0, src.length).parallel().forEach(i -> 
    dst[i] = getKernelValues(3, src, i, width, height).stream() 
        .mapToInt(Integer::intValue) 
        .sum()/9); 

私がここで書いたのは、argb値全体をとるため、完全に間違っています。しかし、多分あなたは私が後で他のフィルタに使うことができる実際の例にそのpiceを変更するのを助けることができます。

ありがとうございます。

編集:
それまでのところ、私は問題を次のように分割することで問題を迂回しました。これは動作しますが、コードは重複しています。誰かがこれをより少ないコードでどのように知っていれば、私は知ってうれしいです。

ありがとうございます。

IntStream.range(0, src.length).parallel().forEach(i -> { 
    ArrayList<Integer> values = getKernelValues(filterSize, src, i, width, height); 
     int r = values 
      .stream() 
      .map(j -> (j >> 16) & 0xff) 
      .reduce(0, (j, k) -> j + k); 
     r /= (filterSize * filterSize); 

     int g = values 
      .stream() 
      .map(j -> (j >> 8) & 0xff) 
      .reduce(0, (j, k) -> j + k); 
     g /= (filterSize * filterSize); 

     int b = values 
      .stream() 
      .map(j -> j & 0xff) 
      .reduce(0, (j, k) -> j + k); 
     b /= (filterSize * filterSize); 

     dst[i] = 0xff << 24 | r << 16 | g << 8 | b; 
}); 
+0

あなたの現在のコードの何が問題になっているのですか? – Tunaki

+0

最後の段落で述べたように、getKernelValues()はargb整数値のArrayListを返します。もちろん、すべてのカラーチャンネルを別々に処理する必要があります。 – amaridev

+0

期待している出力の種類はまだ分かりません。あなたは例を投稿できますか? – Tunaki

答えて

0

r値、g値、b値のすべてを平均する必要があります。私が正しければ、最初に注意しなければならないのは、結果を値の数で除算する前に合計が8ビットを超えるため、intの8ビット空間内の各値を合計できないということです。したがって、最初に行う必要があるのは、r、g、bの値を別々の整数値に抽出して和を保持することです。あなたは、整数フィールドでRGBのクラスを作成することもできますが、整数の配列を行います:

static int[] unpackARGB(int argb){ 
    return new int[] { (argb >> 16) & 0xff, (argb >> 8) & 0xff, argb & 0xff }; 
} 

static int packARGB(int[] ints){ 
    return (0xff << 24 + ints[0] & 0xff) << 16 + (ints[1] & 0xff) << 8 + ints[2] & 0xff; 
} 

あなたは私たちが加算を行うためにintの配列を使用している場合、我々は変換する必要がありますので、ストリームを使いたいですストリームに流れ、そして、加算演算を使用して個々の項目を減らす:

static int[] sumRGB(int[] arr1, int[] arr2){ 
    return new int[] { arr1[0] + arr2[0], arr1[1] + arr2[1], arr1[2] + arr2[2] }; 
} 

その後、我々は戻ってその8ビットの範囲にそれを得るためにそれぞれの値を分割する必要がありますので、この便利なメソッドが役立ちます。

static int[] divRGB(int[] arr1, int divisor){ 
    return new int[] { arr1[0]/divisor, arr1[1]/divisor, arr1[2]/divisor }; 
} 
あなたはこのようにそれを呼び出すことができ、あなたのリストから

public static int averageRGB(IntStream ints, int size) { 
    int[] sum = ints 
      .parallel() 
      .mapToObj(i -> unpackARGB(i)) 
      .reduce(new int[]{0,0,0}, (a, v) -> sumRGB(a, v)); 
    return packARGB(divRGB(sum, size)); 
} 

:210

私たちは、その後、平均演算を実行する関数を作成することができます

int result = averageRGB(integerList.stream().mapToInt(i->i), integerList.size()); 
関連する問題