2016-03-29 7 views
2

私は、すべてのピクセルを取得し、Colorsのリストに保存することにより、与えられた画像の最適なパレット(GIF、最大256色用)を計算しようとしています。Pixels + OrderBy最も頻繁な色を取得

var bmp = new WriteableBitmap(bitmapSource); 
bmp.Lock(); 

int stride = bmp.PixelWidth * 4; 
int size = bmp.PixelHeight * stride; 
var imgData = new byte[size]; 
//int index = y * stride + 4 * x; //To acess a specific pixel. 

Marshal.Copy(bmp.BackBuffer, imgData, 0, imgData.Length); 

bmp.Unlock(); 

var colorList = new List<Color>(); 

//I'm not sure if this is right. 
for (int index = 0; index < imgData.Length - 1; index += 4) 
{ 
    colorList.Add(Color.FromArgb(imgData[index], imgData[index + 1], 
        imgData[index + 2], imgData[index + 3])); 
} 

//Here is the main problem. 
var palette = colorList.Distinct().Take(255); 

現在のところ、すべての色を区別することができ、最初の255色しか使用できません。しかし、私はまず使い方で注文する必要があります。どうやってやるの?

また、他の方法がありますか?

+1

簡単な考えとして、辞書には色をキーとして使用し、その色のピクセル数をカウントする値はintとしてください。 – Pikoh

+0

私はそれについて考えていましたが、ループの中で色を数え、 'Dictionary'を更新する必要がありました。 –

+0

おそらくKのような何かをしたいのは、Kの最も一般的な色を選択するのではなく、クラスタリングを意味します。 –

答えて

2

あなたが最初に、グループにLINQGroupByOrderByDescendingを使用しての考える利用状況(頻度)で注文すると、クエリの結果をソートし、次にだけFirstOrDefaultまたはFirstを使用して、グループの中で最初の要素を取る必要がある場合:

var result = colorList 
       .GroupBy<int, int>(x => x) //grouping based on its value 
       .OrderByDescending(g => g.Count()) //order by most frequent values 
       .Select(g => g.FirstOrDefault()) //take the first among the group 
       .ToList(); //not necessarily put if you want to return IEnumerable 
+0

私はそれを信じています!私は 'int'の代わりに' GroupBy 'に変更し、' ToList() 'の前に' Take(255) 'を追加する必要がありました。 –

+0

@NickeManarinああ、あなたは試してみることができる... :) – Ian

+0

うん、ほとんど白い画像で、最初の色は '白'だった。ありがとう。 –

関連する問題