
程式碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.IO;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ResetImageSettings();
}
Bitmap myBitmap = null;
private void button1_Click(object sender, EventArgs e) ////載入圖檔
{
this.openFileDialog1.Filter = "所有檔案|*.*|BMP File| *.bmp|JPEG File|*.jpg| GIF File|*.gif";
if (openFileDialog1.ShowDialog() == DialogResult.OK) ////由對話框選取圖檔
{
myBitmap = new Bitmap(openFileDialog1.FileName);
pictureBox1.Image = myBitmap;
}
ResetImageSettings();
pictureBox2.Image = null;
}
private void button2_Click(object sender, EventArgs e) ///灰階影像處理
{
int[, ,] ImgData = GetImgData(myBitmap);
ImageAdjust(ImgData, trackBarBright.Value, trackBarContrast.Value, trackBarSaturation.Value);
Bitmap processedBitmap = CreateBitmap(ImgData);
pictureBox2.Image = processedBitmap;
}
private int[, ,] GetImgData(Bitmap myBitmap)
{
int[,,] ImgData = new int[myBitmap.Width, myBitmap.Height, 3];
BitmapData byteArray = myBitmap.LockBits(new Rectangle(0, 0, myBitmap.Width, myBitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int ByteOfSkip = byteArray.Stride - byteArray.Width * 3;
unsafe
{
byte* imgPtr = (byte*)(byteArray.Scan0);
for (int y = 0; y < byteArray.Height; y++)
{
for (int x = 0; x < byteArray.Width; x++)
{
ImgData[x, y, 2] = (int) *(imgPtr);
ImgData[x, y, 1] = (int) *(imgPtr + 1);
ImgData[x, y, 0] = (int) *(imgPtr + 2);
imgPtr += 3;
}
imgPtr += ByteOfSkip;
}
}
myBitmap.UnlockBits(byteArray);
return ImgData;
}
public static Bitmap CreateBitmap(int[, ,] ImgData)
{
int Width = ImgData.GetLength(0);
int Height = ImgData.GetLength(1);
Bitmap myBitmap = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
BitmapData byteArray = myBitmap.LockBits(new Rectangle(0, 0, Width, Height),
ImageLockMode.WriteOnly,
PixelFormat.Format24bppRgb);
//Padding bytes的長度
int ByteOfSkip = byteArray.Stride - myBitmap.Width * 3;
unsafe
{ // 指標取出影像資料
byte* imgPtr = (byte*) byteArray.Scan0;
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
*imgPtr = (byte)ImgData[x, y, 2]; //B
*(imgPtr+1) = (byte)ImgData[x, y, 1]; //G
*(imgPtr+2) = (byte)ImgData[x, y, 0]; //R
imgPtr += 3;
}
imgPtr += ByteOfSkip; // 跳過Padding bytes
}
}
myBitmap.UnlockBits(byteArray);
return myBitmap;
}
private void ImageAdjust(int[, ,] ImgData, int Brightness, int Contrast, int Saturation)
{
int Width = ImgData.GetLength(0);
int Height = ImgData.GetLength(1);
int R, G, B;
int Y, Cb, Cr;
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
R = ImgData[x, y, 0]; G = ImgData[x, y, 1]; B = ImgData[x, y, 2];
Y = (int) ((double) R * 0.299 + (double) G * 0.587 + (double) B * 0.114);
Y = Math.Max(Math.Min(Y, 255), 0);
Cb = (int)((double)R * -0.16874 + (double)G * -0.33126 + (double)B * 0.50000) + 128;
Cb = Math.Max(Math.Min(Cb, 255), 0);
Cr = (int)((double)R * 0.50000 + G * -0.41869 + (double)B * -0.08131) + 128;
Cr = Math.Max(Math.Min(Cr, 255), 0);
Y = (int) ((double)(Contrast + 100) * (double)Y / (double)100) + Brightness;
Y = Math.Max(Math.Min(Y, 255), 0);
Cb = (int) ((double) (Cb - 128 ) * (double) (Saturation + 100) / 100.0) + 128;
Cr = (int) ((double)(Cr - 128) * (double)(Saturation + 100) / 100.0) + 128;
ImgData[x, y, 0] = (int)((double)Y + 1.402 * (double)(Cr - 128));
ImgData[x,y,0] = Math.Max(Math.Min(ImgData[x,y,0], 255), 0);
ImgData[x, y, 1] = (int)((double)Y - 0.34414 * (double)(Cb - 128) - 0.71414 * (double)(Cr - 128));
ImgData[x,y,1] = Math.Max(Math.Min(ImgData[x,y,1], 255), 0);
ImgData[x, y, 2] = (int)((double)Y + 1.772 * (double)(Cb - 128));
ImgData[x,y,2] = Math.Max(Math.Min(ImgData[x,y,2], 255), 0);
}
}
}
private void btnSaveImg_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
string curDir;
curDir = Directory.GetCurrentDirectory();
saveFileDialog1.InitialDirectory = curDir;
saveFileDialog1.Filter = "JPG File|*.jpg";
saveFileDialog1.Title = "儲存影像檔";
saveFileDialog1.FilterIndex = 3;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
saveJpeg(saveFileDialog1.FileName, myBitmap, 85);
}
}
private void saveJpeg(string path, Bitmap img, long quality)
{
// Encoder parameter for image quality
EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, quality);
// Jpeg image codec
ImageCodecInfo jpegCodec = this.getEncoderInfo("image/jpeg");
if (jpegCodec == null)
return;
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
img.Save(path, jpegCodec, encoderParams);
}
private ImageCodecInfo getEncoderInfo(string mimeType)
{
// Get image codecs for all image formats
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
// Find the correct image codec
for (int i = 0; i < codecs.Length; i++)
if (codecs[i].MimeType == mimeType)
return codecs[i];
return null;
}
private void trackBarBright_Scroll(object sender, EventArgs e)
{
lblBrightValue.Text = String.Format("{0:D}", trackBarBright.Value);
}
private void trackBarContrast_Scroll(object sender, EventArgs e)
{
lblContrastValue.Text = String.Format("{0:D}", trackBarContrast.Value);
}
private void trackBarSaturation_Scroll(object sender, EventArgs e)
{
lblSaturationValue.Text = String.Format("{0:D}", trackBarSaturation.Value);
}
private void ResetImageSettings()
{
trackBarBright.Value = 0; trackBarContrast.Value = 0; trackBarSaturation.Value = 0;
lblBrightValue.Text = String.Format("{0:D}", trackBarBright.Value);
lblContrastValue.Text = String.Format("{0:D}", trackBarContrast.Value);
lblSaturationValue.Text = String.Format("{0:D}", trackBarSaturation.Value);
}
}
}
參考文章:ColorMatrix Image Hue Saturation Contrast Brightness in C# .NET GDI+
文章定位: