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);
}
}
}

