2009-12-31 24 views

回答

3

一個簡單但不夠高效的解決方案是將尺寸調整爲較小尺寸,然後使用像素重複調整尺寸。

更好的解決方案將是(僞代碼):
(時間爲O(n),另外的空間(除了可變源圖像):O(1))

// Pixelize in x axis (choose a whole k s.t. 1 <= k <= Width) 
var sum = Pixel[0, 0]; 
for (y = 0; y < Height; y++) 
{ 
    for (x = 0; x < Width + 1; x++) 
    { 
     if (x % k == 0) 
     { 
      sum /= k; 
      for (xl = Max(0, x-k); xl < x; xl++) 
       Pixel[y, xl] = sum; 
      sum = 0; 
     } 
     if (x == Width) 
      break; 
     sum += Pixel[y, x]; 
    } 
} 

// Now do the same in the y axis 
// (make sure to keep y the outer loop - for better performance) 

// If your image has more than one channel, then then Pixel should be a struct. 
0

雖然我不知道這個知名的算法,但我確實必須寫類似的東西。我使用的技術非常簡單,但我認爲對於大圖像效率不高。基本上我會拍攝圖像,並在5(或更高的像素塊)像素塊中進行顏色平均,然後使所有這些像素具有相同的顏色。你可以通過對對角像素進行平均來加快速度,這可以節省很多週期,但不夠準確。

1

this forum的人過有一個相當不錯的算法。它通過獲取每個「塊」中所有顏色的平均值來工作。

我只是用他在C#/ GDI +今天實現:

using System; 
using System.Collections.Generic; 
using System.Diagnostics.CodeAnalysis; 
using System.Drawing; 
using System.Linq; 
using System.Text; 

/// <summary> 
/// Applies a pixelation effect to an image. 
/// </summary> 
[SuppressMessage(
    "Microsoft.Naming", 
    "CA1704", 
    Justification = "'Pixelate' is a word in my book.")] 
public class PixelateEffect : EffectBase 
{ 
    /// <summary> 
    /// Gets or sets the block size, in pixels. 
    /// </summary> 
    private int blockSize = 10; 

    /// <summary> 
    /// Gets or sets the block size, in pixels. 
    /// </summary> 
    public int BlockSize 
    { 
     get 
     { 
      return this.blockSize; 
     } 

     set 
     { 
      if (value <= 1) 
      { 
       throw new ArgumentOutOfRangeException("value"); 
      } 

      this.blockSize = value; 
     } 
    } 

    /// <summary> 
    /// Applies the effect by rendering it onto the target bitmap. 
    /// </summary> 
    /// <param name="source">The source bitmap.</param> 
    /// <param name="target">The target bitmap.</param> 
    public override void DrawImage(Bitmap source, Bitmap target) 
    { 
     if (source == null) 
     { 
      throw new ArgumentNullException("source"); 
     } 

     if (target == null) 
     { 
      throw new ArgumentNullException("target"); 
     } 

     if (source.Size != target.Size) 
     { 
      throw new ArgumentException("The source bitmap and the target bitmap must be the same size."); 
     } 

     using (var graphics = Graphics.FromImage(target)) 
     { 
      graphics.PageUnit = GraphicsUnit.Pixel; 

      for (int x = 0; x < source.Width; x += this.BlockSize) 
      { 
       for (int y = 0; y < source.Height; y += this.BlockSize) 
       { 
        var sums = new Sums(); 

        for (int xx = 0; xx < this.BlockSize; ++xx) 
        { 
         for (int yy = 0; yy < this.BlockSize; ++yy) 
         { 
          if (x + xx >= source.Width || y + yy >= source.Height) 
          { 
           continue; 
          } 

          var color = source.GetPixel(x + xx, y + yy); 
          sums.A += color.A; 
          sums.R += color.R; 
          sums.G += color.G; 
          sums.B += color.B; 
          sums.T++; 
         } 
        } 

        var average = Color.FromArgb(
         sums.A/sums.T, 
         sums.R/sums.T, 
         sums.G/sums.T, 
         sums.B/sums.T); 

        using (var brush = new SolidBrush(average)) 
        { 
         graphics.FillRectangle(brush, x, y, (x + this.BlockSize), (y + this.BlockSize)); 
        } 
       } 
      } 
     } 
    } 

    /// <summary> 
    /// A structure that holds sums for color averaging. 
    /// </summary> 
    private struct Sums 
    { 
     /// <summary> 
     /// Gets or sets the alpha component. 
     /// </summary> 
     public int A 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// Gets or sets the red component. 
     /// </summary> 
     public int R 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// Gets or sets the blue component. 
     /// </summary> 
     public int B 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// Gets or sets the green component. 
     /// </summary> 
     public int G 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// Gets or sets the total count. 
     /// </summary> 
     public int T 
     { 
      get; 
      set; 
     } 
    } 
} 

買者自負,工作我的機器上,&等

相關問題