【提示:為了方便大家閱讀並尋求參考,文中的超連結均串連到MSDN中的相應內容。】
前些天開始研究WPF。是從圖片的顯示、編輯和儲存開始研究的。
在我看來,WPF和以前的Form在圖片處理方面的變化太大了。它們分別用了不同的類來表示圖片。在From中用的是Image類;而在WPF中,Image已經作為顯示圖片用的控制項了,表示圖片的類是ImageSource、BitmapSource、BitmapImage、 WriteableBitmap等。現在還不是很清楚這些類的特點和具體應用方面。
不過前些天遇到的問題(http://student.csdn.net/space.php?uid=127131&do=thread&id=10182)也算是通過努力解決了。
現在就總結一下:
1、首先要瞭解圖片的格式。
我所用的源圖片都是jpg或bmp格式的。在這兩種格式圖片中一般都是用R、G、B三個元素表示一個像素。所以在程式中每個像素都是用3個byte型的變數表示的。
這裡面還應該說一下。當對圖片進行像素的讀取操作時,圖片的Width和height應該用PixelWidth和PixelHeight屬性擷取。因為在WPF中Width和height屬性是double型的,它用來表示映像的顯示尺寸,而不是實際尺寸。
2、讀入並用Image控制項顯示圖片。
在WPF中,感覺檔案的路徑好多都要轉化成Uri類的對象才能很方便地使用。要讀片當然利用OpenFileDialog先找到圖片的路徑fileName(當然是string型的)。然後建立一個Uri fileUri=new Uri(fileName);。之後,我利用BitmapDecoder類將圖片解碼,並將解碼後的圖片送到Image控制項中顯示。至於Create中的後兩個參數我也不是很明白,只知道這樣做沒有錯。
Code:
- Uri fileUri=new Uri(fileName);
- BitmapDecoder decoder = BitmapDecoder.Create(fileUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
- image1.Source = decoder.Frames[0];
3、其次要找到方法將圖片的像素讀出來,並將修改後的像素寫回去。
在以上提到的WPF中表示圖片的四個類中,BitmapSource、BitmapImage、 WriteableBitmap都具有CopyPixels方法。用這個方法就可以將映像中的像素讀出來。其原型為public virtual void CopyPixels(Array pixels,int stride, int offset)【這裡只介紹這一種重載方式】。
Array pixels:執行此函數後,這個變數裡面的值就是所要取得的圖片像素資料。在調用這個函數之前可以先聲明一個byte型數組(如byte[] imgPixels = new byte[像素個數×每個像素所含元素個數]);
int stride:stride原意為跨越、步幅。經過我分析,感覺它在這裡表示圖片的一行所需要的byte數量。也就是【每行像素個數×每個像素元素個數】;
int offset:這個比較好理解,就是從哪裡(用像素表示的位置)開始copy pixels。
4、對像素資料(imgPixels 數組)進行操作。
這裡我就不說了,您隨意!
5、用修改後的資料產生新的映像。
上面說擷取像素時,BitmapSource、BitmapImage、 WriteableBitmap都可以,但是利用像素產生圖片時,卻只有WriteableBitmap才能勝任。因為只有它才具有WritePixels方法。其原型為public void WritePixels(Int32Rect sourceRect,Array pixels,int stride,int offset)【這裡只介紹這一種重載方式】。
Int32Rect sourceRect:需要更新的地區,也就是需要用像素資料更改的地區。如果建立一張新圖片的話,那這裡就是new Int32Rect(0,0,PixelWidth,PixelHeight)了;
Array pixels和int stride就不多解釋了,含義和用法同上;
int offset:還是有必要說一下的。在這裡,它指的是像素資料的位移量,也就是pixels數組的位移量,而不是像素的位移量。
這裡面,WriteableBitmap類型的圖片可以很方便轉換成其他幾種圖片類型。
6、儲存剛剛產生的圖片。
由於我是對像素進行的操作,並向讓再次開啟圖片是能夠知道我對象度進行了哪些操作,所以我將映像儲存成Bmp格式。這裡面的重點是要用BitmapEncoder類將映像編碼。當然不同映像格式有不同的類繼承自BitmapEncoder類,向這裡就用到了BitmapEncoder類的子類BmpBitmapEncoder。不多解釋了,代碼如下:
Code:
- static public void SaveImage(string file, BitmapSource img)
- {
- BmpBitmapEncoder encoder = new BmpBitmapEncoder();
- encoder.Frames.Add(BitmapFrame.Create(img));
-
- FileStream bitmap = new FileStream(file, FileMode.Create, FileAccess.Write);
- encoder.Save(bitmap);
- bitmap.Close();
- }
就這樣,有興趣的可以試一試。
另外我初學WPF,有什麼說的不對的,還請大家協助批評指導啊!