C#圖片處理

來源:互聯網
上載者:User
文章目錄
  • 1,圖片格式轉換
  • 2,圖片的縮放(Scale)
  • 3,圖片的翻轉(Rotate)
  • 4,圖片的截取(Clip)
  • 5,濾鏡(Filter)

通常對一幅圖片的處理包括:格式變換,縮放(Scale),翻轉(Rotate),截取(Clip),濾鏡(Filter,如高斯模糊)等。

1,圖片格式轉換

.NET中的Image類是對圖片對象的封裝,我們可以通過操作Image類的執行個體來處理圖片。通常我們有兩種式可以得到Image執行個體:

var imgPng = Image.FromFile(@"C:\temp\img\pp.png");byte[] raw = ReadFromFileOrNetwork();var imgBmp = Image.FromStream(new MemoryStream(raw));

 

1.1判斷圖片格式

var imgJpg = Image.FromFile(@"C:\temp\img\jj.jpg");if (imgJpg.RawFormat.Equals(ImageFormat.Jpeg)){    MessageBox.Show("Jpeg");}

注意這裡使用ImageFormat.Equals方法,而不能使用==,如果非要使用等號,可以:

if (imgPng.RawFormat.Guid == ImageFormat.Png.Guid){    MessageBox.Show("Png");}

1.2,圖片格式轉換

imgPng.Save(@"c:\temp\img\newBmp.bmp", ImageFormat.Jpeg);

 

2,圖片的縮放(Scale)

圖片的放大,縮小,展開可以通過Image執行個體的GetThumbnailImage來實現

//縮小var newPng = imgPng.GetThumbnailImage(imgPng.Width / 2, imgPng.Height / 2, () => { return false; }, IntPtr.Zero);newPng.Save(@"c:\temp\img\newPng.png");//放大var newJpg = newPng.GetThumbnailImage(imgPng.Width * 2, imgPng.Height * 2, () => { return false; }, IntPtr.Zero);newJpg.Save(@"c:\temp\img\newJpg.jpg", ImageFormat.Jpeg);//展開(Stretch)var newGif = newPng.GetThumbnailImage(imgPng.Width * 2, imgPng.Height  /2, () => { return false; }, IntPtr.Zero);newGif.Save(@"c:\temp\img\newGif.gif", ImageFormat.Gif);

 

3,圖片的翻轉(Rotate)

圖片的翻轉通過Image.RotateFlip方法來實現

//翻轉imgPng.RotateFlip(RotateFlipType.Rotate180FlipX);imgPng.Save(@"c:\temp\img\newPng.png");

可以通過RotateFlipType調整翻轉的角度

 

4,圖片的截取(Clip)

有時我們只想要圖片的一部分,比如左邊100個像素,而不是整個圖片。我們可以通過兩種方式來實現。

4.1,拷貝原圖片的部分像素

Rectangle rect = new Rectangle(0, 0, imgPng.Width / 2, imgPng.Height);Bitmap clipPng = new Bitmap(imgPng).Clone(rect, imgPng.PixelFormat);clipPng.Save(@"c:\temp\img\clipPng.png");

 

4.2,畫出部分圖片

Rectangle rect = new Rectangle(0, 0, imgPng.Width / 3, imgPng.Height);  //target sizeBitmap canvas = new Bitmap(rect.Width,rect.Height);                     //create canvas(width&heigh same as target)using (Graphics g = Graphics.FromImage(canvas)){    g.DrawImageUnscaledAndClipped(imgPng, rect);}canvas.Save(@"c:\temp\img\canvas.png");

 

5,濾鏡(Filter)

通常我們對圖片使用濾鏡,就是對圖片的像素點進行矩陣變換(Matrix)。我們先從單個像素點的處理開始:

5.1,顏色反轉(Color Invert)

Color Invert是指對位元影像的每個像素取其反色,Jpg和Bmp格式的顏色是以RGB(Red Green Blue)來表示的,也就是每個像素點由RGB三種顏色來組成。Png由於可以設定為透明,所以加了一個Alpha通道,也就是說Png是用RGBA來表示的。

有一點需要注意的是,我們使用Image來擷取的顏色表示並不是RGB而是BGR,準確地說這是GD+在底層返回的就不是RGB,而是BGR這點需要特別注意。對於Png檔案我們還可以通過Alpha通道來設定圖片的透明度。

/* Usage:    InvertColor(@"C:\temp\img\colorInvert.png", @"C:\temp\img\colorInvert-1.png");*/private static void InvertColor(string srcFileName,string destFileName){    var bitPic = new Bitmap(srcFileName);    if (!(bitPic.RawFormat.Equals(ImageFormat.Bmp) ||         bitPic.RawFormat.Equals(ImageFormat.Jpeg) ||         bitPic.RawFormat.Equals(ImageFormat.Png)))    {        MessageBox.Show("Unsuported format,only support for bmp,jpg or png");        return;    }    Rectangle rect = new Rectangle(0, 0, bitPic.Width, bitPic.Height);    var bmpData = bitPic.LockBits(rect, ImageLockMode.ReadWrite, bitPic.PixelFormat); // GDI+ still lies to us - the return format is BGR, NOT RGB.     IntPtr ptr = bmpData.Scan0;    // Declare an array to hold the bytes of the bitmap.    int totalPixels = Math.Abs(bmpData.Stride) * bitPic.Height; //Stride tells us how wide a single line is,width*heith come up with total pixel    byte[] rgbValues = new byte[totalPixels];    // Copy the RGB values into the array.    Marshal.Copy(ptr, rgbValues, 0, totalPixels); //RGB=>rgbValus    if (bitPic.RawFormat.Equals(ImageFormat.Bmp) || bitPic.RawFormat.Equals(ImageFormat.Jpeg))    {        int b = 0, g = 1, r = 2;  //BGR        for (int i = 0; i < totalPixels; i += 3)        {            rgbValues[r + i] = (byte)(255 - rgbValues[r + i]);            rgbValues[g + i] = (byte)(255 - rgbValues[g + i]);            rgbValues[b + i] = (byte)(255 - rgbValues[b + i]);        }    }    else if (bitPic.RawFormat.Equals(ImageFormat.Png))    {        int b = 0, g = 1, r = 2, a = 3;  //BGRA        for (int i = 0; i < totalPixels; i += 4)        {            rgbValues[r + i] = (byte)(255 - rgbValues[r + i]);            rgbValues[g + i] = (byte)(255 - rgbValues[g + i]);            rgbValues[b + i] = (byte)(255 - rgbValues[b + i]);            rgbValues[a + i] = 255;  //NOTE:you can set (255*threshold) for transparency.        }    }    Marshal.Copy(rgbValues, 0, ptr, totalPixels);    bitPic.UnlockBits(bmpData);    bitPic.Save(destFileName);}

對於GIF,由於他並不是按RGB的顏色來編碼,而是用另一種256色的顏色編碼,我稍後再研究:)

 

5.2,灰階圖(Grayscale)

Grayscale就是將每像素點的RGB值作平均,即第個像素的RGB分量值都是一樣的。這樣做的目的就因為等值的RGB(R=G=B)就是從黑到白的顏色區間,我們可以通過GIMP看下:

當每個像素點的組成RGB相等時,該點必定是灰色調的。

我們的代碼也有調整,這次使用Bitmap.GetPixel來得到圖片的RGB值,這樣就不需要對圖片的格式進行特別處理了。不過還是不可以處理Gif等使用Indexed Color的圖片。

private void Grayscale(string srcFileName, string destFileName){    var bitPic = new Bitmap(srcFileName);    if (!(bitPic.RawFormat.Equals(ImageFormat.Bmp) ||        bitPic.RawFormat.Equals(ImageFormat.Jpeg) ||        bitPic.RawFormat.Equals(ImageFormat.Png)))    {        MessageBox.Show("Unsuported format,only support for bmp,jpg or png");        return;    }    int rgb;    Color c;    for (int y = 0; y < bitPic.Height; y++)    {        for (int x = 0; x < bitPic.Width; x++)        {            c = bitPic.GetPixel(x, y);            rgb = (int)((c.R + c.G + c.B) / 3);  //We can adjust this calc as needed, such as Max(r,g,b),Min(r,g,b),(.299*r +.587*g.+ .114*b)            bitPic.SetPixel(x, y, Color.FromArgb(rgb, rgb, rgb));        }    }    bitPic.Save(destFileName);}

 

5.3,明亮度(Brightness)

電腦中顏色(Color)是用RGB來表示的,但我們人眼對色彩的認識的模式是HSV(純度Hue,飽和度Saturation,亮度Value或Luminance)。我們可以使得RGB的每個分量的值增大來讓圖片變亮,也可以使每個分量變小來讓圖片變暗。而HSV模式的明暗設定就更簡單了,只需改V分量值即可以改變圖片的明暗。關於RGB到HSL/HSV的轉換演算法可以看Wikipedia。有一點需要注意的就是.net中Color類的GetHue,GetSaturation,GetBrightness擷取的是HSL值而不是HSV值。

3.1,通過RGB來改變明暗度

private void Brightness(string srcFileName, string destFileName, float grain){    var bitPic = new Bitmap(srcFileName);    if (!(bitPic.RawFormat.Equals(ImageFormat.Bmp) ||        bitPic.RawFormat.Equals(ImageFormat.Jpeg) ||        bitPic.RawFormat.Equals(ImageFormat.Png)))    {        MessageBox.Show("Unsuported format,only support for bmp,jpg or png");        return;    }    Color c;    Func<int, int> notOver255 = (x) => { return x > 255 ? 255 : x; };    for (int y = 0; y < bitPic.Height; y++)    {        for (int x = 0; x < bitPic.Width; x++)        {            c = bitPic.GetPixel(x, y);            Color brightColor = Color.FromArgb(                notOver255((int)(c.R * grain)),                 notOver255((int)(c.G * grain)),                 notOver255((int)(c.B * grain)));            bitPic.SetPixel(x, y, brightColor);        }    }    bitPic.Save(destFileName);}

 

3.2通過HSV中V分量來改變圖片明暗度

稍後研究,還有個問題就是改變圖片的明暗度後,Png和Jpg圖片的大小產生了變化,換個說法就是RGB分量值會影響Png和Jpg壓縮。

 

 

Reference:

1,http://www.codeproject.com/Articles/1989/Image-Processing-for-Dummies-with-C-and-GDI-Part-1

2,http://en.wikipedia.org/wiki/HSL_and_HSV

3,http://stackoverflow.com/questions/359612/how-to-change-rgb-color-to-hsv

4,http://www.cnblogs.com/sndnnlfhvk/archive/2012/02/27/2370643.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.