2011-10-05 66 views
3

我將圖像加載到BitmapImage並將其轉換爲PixelColor的數組。我想要的是能夠操縱這些像素中的一些來使它們更輕/更深/透明,但我似乎無法使其工作。它可以將其設置爲某種顏色,但alpha通道將被忽略。圖像的減輕/變暗/透明部分

它使用C#4

由於是一個WPF應用程序!
和代碼...

namespace BitmapTest { 
using System; 
using System.Drawing; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Interop; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using Image = System.Windows.Controls.Image; 

public partial class MainWindow { 
    public MainWindow() { 
     InitializeComponent(); 
     LoadImage(); 
    } 

    [DllImport("gdi32")] 
    private static extern int DeleteObject(IntPtr o); 

    public static BitmapSource LoadBitmap(Bitmap source) { 
     var ip = source.GetHbitmap(); 
     try { 
      return Imaging.CreateBitmapSourceFromHBitmap(ip, 
                 IntPtr.Zero, Int32Rect.Empty, 
                 BitmapSizeOptions.FromEmptyOptions()); 
     } finally { 
      DeleteObject(ip); 
     } 
    } 

    private void LoadImage() { 
     var i = new Image(); 
     var src = new BitmapImage(); 
     src.BeginInit(); 
     src.UriSource = new Uri("road.jpg", UriKind.Relative); 
     src.CacheOption = BitmapCacheOption.OnLoad; 
     src.EndInit(); 

     var pixels = GetPixels(src); 
     for (var x = 0; x < Math.Min(50, pixels.GetLength(0)); x++) { 
      for (var y = 0; y < Math.Min(50, pixels.GetLength(1)); y++) { 
       pixels[x, y] = new PixelColor {Alpha = 100, Red = pixels[x, y].Red, Green = pixels[x, y].Green, Blue = pixels[x, y].Blue}; 
      } 
     } 

     var bitmap = new WriteableBitmap(src.PixelWidth, src.PixelHeight, src.DpiX, src.DpiY, src.Format, src.Palette); 
     PutPixels(bitmap, pixels, 0, 0); 

     i.Source = bitmap; 
     i.Stretch = Stretch.Fill; 
     RootGrid.Children.Add(i); 
    } 

    public PixelColor[,] GetPixels(BitmapSource source) { 
     if (source.Format != PixelFormats.Bgra32) 
      source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0); 

     var pixels = source.CopyPixels(); 
     return pixels; 
    } 

    public void PutPixels(WriteableBitmap bitmap, PixelColor[,] pixels, int x, int y) { 
     var width = pixels.GetLength(0); 
     var height = pixels.GetLength(1); 
     var sourceRect = new Int32Rect(0, 0, width, height); 
     bitmap.WritePixels(sourceRect, pixels, width*4, x, y); 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct PixelColor { 
     public byte Blue; 
     public byte Green; 
     public byte Red; 
     public byte Alpha; 
    } 
} 


public static class BitmapSourceHelper { 
    public static MainWindow.PixelColor[,] CopyPixels(this BitmapSource source) { 
     if (source.Format != PixelFormats.Bgra32) 
      source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0); 
     var pixels = new MainWindow.PixelColor[source.PixelWidth, source.PixelHeight]; 
     var stride = source.PixelWidth * ((source.Format.BitsPerPixel + 7)/8); 
     var pinnedPixels = GCHandle.Alloc(pixels, GCHandleType.Pinned); 
     source.CopyPixels(
      new Int32Rect(0, 0, source.PixelWidth, source.PixelHeight), 
      pinnedPixels.AddrOfPinnedObject(), 
      pixels.GetLength(0) * pixels.GetLength(1) * 4, 
      stride); 
     pinnedPixels.Free(); 
     return pixels; 
    } 
} 
} 

回答

3

這裏是閃電和Windows窗體應用程序變暗的圖像的例子。此處的代碼基於代碼項目網站上文章的亮度過濾器部分:Image Processing for Dummies with C# and GDI+ Part 1

public Bitmap Lighten(Bitmap bitmap, int amount) 
{ 
    if (amount < -255 || amount > 255) 
    return bitmap; 

    // GDI+ still lies to us - the return format is BGR, NOT RGB. 
    BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 

    int stride = bmData.Stride; 
    System.IntPtr Scan0 = bmData.Scan0; 

    int nVal = 0; 

    unsafe 
    { 
    byte* p = (byte*)(void*)Scan0; 

    int nOffset = stride - bitmap.Width * 3; 
    int nWidth = bitmap.Width * 3; 

    for (int y = 0; y < bitmap.Height; ++y) 
    { 
     for (int x = 0; x < nWidth; ++x) 
     { 
     nVal = (int)(p[0] + amount); 

     if (nVal < 0) nVal = 0; 
     if (nVal > 255) nVal = 255; 

     p[0] = (byte)nVal; 

     ++p; 
     } 
     p += nOffset; 
    } 
    } 

    bitmap.UnlockBits(bmData); 

    return bitmap; 
} 

private void btnLighten_Click(object sender, EventArgs e) 
{ 
    Bitmap image = pictureBox1.Image as Bitmap; 
    pictureBox1.Image = Lighten(image, 10); 
} 

private void btnDarken_Click(object sender, EventArgs e) 
{ 
    Bitmap image = pictureBox1.Image as Bitmap; 
    pictureBox1.Image = Lighten(image, -10); 
} 
0

此代碼將調整圖像中的給定的矩形,根據亮度,對比度,α,γ:

Bitmap clonedImage = originalImage.Clone(rect, originalImage.PixelFormat); 
float gamma = 1.0f; // no change in gamma 

float adjustedBrightness = brightness - 1.0f; 
// create matrix that will brighten and contrast the image 
float[][] ptsArray ={ 
     new float[] {contrast, 0, 0, 0, 0}, // scale red 
     new float[] {0, contrast, 0, 0, 0}, // scale green 
     new float[] {0, 0, contrast, 0, 0}, // scale blue 
     new float[] {0, 0, 0, alpha, 0}, 
     new float[] {adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1}}; 

var imageAttributes = new ImageAttributes(); 
imageAttributes.ClearColorMatrix(); 
imageAttributes.SetColorMatrix(new ColorMatrix(ptsArray), ColorMatrixFlag.Default, ColorAdjustType.Bitmap); 
imageAttributes.SetGamma(gamma, ColorAdjustType.Bitmap); 

// Copy back to the original image from the cloned image 
Graphics g = Graphics.FromImage(originalImage); 
g.DrawImage(clonedImage, new Rectangle(0, 0, clonedImage.Width, clonedImage.Height) 
    , rect.left, rect.top, rect.Width, rect.Height, 
    GraphicsUnit.Pixel, imageAttributes); 
g.Flush();