Nadesłany przez Tomasz Lubiński, 14 czerwca 2012 21:06
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
sepia/Form1.cs:
//Sepia - efekt starego zdjecia //(c) 2012 by Tomasz Lubinski //www.algorytm.org using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using System.Drawing.Imaging; namespace sepia { public partial class Form1 : Form { /// <summary> /// Obraz zrodlowy i wynikowy /// </summary> private Image zrodlo; private int bytesPerPixel; private Obraz wynik; /// <summary> /// Zainicjuj /// </summary> public Form1() { zrodlo = null; bytesPerPixel = 0; InitializeComponent(); trackBar1_ValueChanged(null, null); } /// <summary> /// Wczytaj obraz /// </summary> private void wczytaj_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Otwórz obraz"; dlg.Filter = "pliki jpg (*.jpg)|*.jpg|pliki png (*.png)|*.png|wszystkie pliki (*.*)|*.*"; if (dlg.ShowDialog() == DialogResult.OK) { zrodlo = new Bitmap(dlg.OpenFile()); bytesPerPixel = Image.GetPixelFormatSize(zrodlo.PixelFormat) / 8; wynik = new Obraz(); wynik.obrazWynikowy.Image = new Bitmap(dlg.OpenFile()); wynik.obrazWynikowy.Height = wynik.obrazWynikowy.Image.Height; wynik.obrazWynikowy.Width = wynik.obrazWynikowy.Image.Width; wynik.obrazWynikowy.Refresh(); wynik.ClientSize = new System.Drawing.Size(wynik.obrazWynikowy.Width + 24, wynik.obrazWynikowy.Height + 32); wynik.Show(); wynik.Refresh(); } dlg.Dispose(); } /// <summary> /// Sepia /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void trackBar1_ValueChanged(object sender, EventArgs e) { //Nie rob nic wiecej jezeli obraz jest jeszcze niewczytany if (zrodlo == null) { return; } //Sprawdz czy obraz wynikowy bedzie kolorowy if (bytesPerPixel < 3) { MessageBox.Show("Nieprawidłowy format pliku wejściowego"); } //Pobierz wartosc sepii int sepia = suwak.Value; //Przygotuj tablice LUT dla kanalu R (czerwien) byte[] LUTR = new byte[256]; for (int i = 0; i < 256; i++) { if (i + 2 * sepia > 255) { LUTR[i] = 255; } else { LUTR[i] = (byte)(i + 2 * sepia); } } //Przygotuj tablice LUT dla kanalu G (zielen) byte[] LUTG = new byte[256]; for (int i = 0; i < 256; i++) { if (i + sepia > 255) { LUTG[i] = 255; } else { LUTG[i] = (byte)(i + sepia); } } //Kopiuj obrazek zrodlowy Bitmap bitmap = (Bitmap)zrodlo.Clone(); wynik.obrazWynikowy.Image = bitmap; //Pobierz wartosc wszystkich punktow obrazu BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); byte[] pixelValues = new byte[Math.Abs(bmpData.Stride) * bitmap.Height]; System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, pixelValues, 0, pixelValues.Length); //Sepia dla kazdego punktu obrazu for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { int index = y * bmpData.Stride + x * bytesPerPixel; int val = (int)(0.299 * pixelValues[index + 2] + 0.587 * pixelValues[index + 1] + 0.114 * pixelValues[index]); pixelValues[index + 2] = LUTR[val]; pixelValues[index + 1] = LUTG[val]; pixelValues[index] = (byte)val; } } //Ustaw wartosc wszystkich punktow obrazu System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, bmpData.Scan0, pixelValues.Length); bitmap.UnlockBits(bmpData); } } }