using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using Pfz.Drawing;
using Pfz.Drawing.Extensions.BitmapExtensions;
using Pfz.Threading;
using Pfz.Drawing.Extensions.ManagedBitmapIntExtensions;
namespace PfzDrawingSample
{
public partial class Form1 : Form
{
private ArgbBitmap fOriginalBitmap;
private ArgbBitmap fBitmap;
private bool fGenerateNew;
private int fGenerationCount;
public Form1()
{
InitializeComponent();
comboMethod.SelectedIndex = 0;
}
protected override void OnPaintBackground(PaintEventArgs e)
{
}
private void buttonLoad_Click(object sender, EventArgs e)
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
using(var systemBitmapOnly = (Bitmap)Image.FromFile(openFileDialog.FileName))
{
var originalBitmap = new ArgbBitmap(systemBitmapOnly);
var bitmap = new ArgbBitmap(originalBitmap.Width, originalBitmap.Height);
// if boths bitmaps where allocated with success, there is no more chance
// of exceptions, so we can dispose the old bitmaps (if they existed) and
// replace with the new ones.
if (fBitmap != null)
fBitmap.Dispose();
if (fOriginalBitmap != null)
fOriginalBitmap.Dispose();
fOriginalBitmap = originalBitmap;
fBitmap = bitmap;
}
fGenerateNew = true;
buttonSave.Enabled = true;
Invalidate();
}
catch(Exception exception)
{
MessageBox.Show(exception.Message, exception.GetType().FullName);
}
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// If an image was not loaded we clear and return.
if (fOriginalBitmap == null)
{
e.Graphics.FillRectangle(Brushes.Black, e.ClipRectangle);
return;
}
int width = fOriginalBitmap.Width;
int height = fOriginalBitmap.Height;
var originalBitmap = fOriginalBitmap.AsSystemBitmap;
var bitmap = fBitmap.AsSystemBitmap;
// If we need to generate a new image, we will get the pixels from
// the original image, modify the color by the tracks and then apply the
// changed to the "managedbitmap" that we already pre-allocated with the
// same width and height.
if (fGenerateNew)
{
fGenerateNew = false;
// it is REALLY important to get these values before starting the
// processment. In my first version everything was really slow because
// I was re-reading the value properties at each pixel.
int trackBarRedValue = trackBarRed.Value;
int trackBarGreenValue = trackBarGreen.Value;
int trackBarBlueValue = trackBarBlue.Value;
fGenerationCount++;
DateTime begin = DateTime.Now;
switch(comboMethod.SelectedIndex)
{
case 0:
int[] sourceArray = fOriginalBitmap.PixelArray;
int[] destArray = fBitmap.PixelArray;
int count = sourceArray.Length;
for(int i=0; i<count; i++)
{
Color color = Color.FromArgb(sourceArray[i]);
int r = p_Calculate(color.R, trackBarRedValue);
int g = p_Calculate(color.G, trackBarGreenValue);
int b = p_Calculate(color.B, trackBarBlueValue);
destArray[i] = Color.FromArgb(r, g, b).ToArgb();
}
break;
case 1:
for (int y=0; y<height; y++)
{
for(int x=0; x<width; x++)
{
Color color = originalBitmap.GetPixel(x, y);
int r = p_Calculate(color.R, trackBarRedValue);
int g = p_Calculate(color.G, trackBarGreenValue);
int b = p_Calculate(color.B, trackBarBlueValue);
bitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
}
}
break;
case 2:
BitmapData sourceData = null;
BitmapData destData = null;
AbortSafe.Run
(
() =>
{
sourceData = originalBitmap.LockBits(new Rectangle(new Point(), originalBitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
destData = bitmap.LockBits(new Rectangle(new Point(), bitmap.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
},
() =>
{
Size size = originalBitmap.Size;
unsafe
{
byte *sourceScanlineBytes = (byte *)sourceData.Scan0;
byte *destScanlineBytes = (byte *)destData.Scan0;
for(int y=0; y<size.Height; y++)
{
int *sourceScanline = (int *)sourceScanlineBytes;
int *destScanline = (int *)destScanlineBytes;
for(int x=0; x<size.Width; x++)
{
int color = sourceScanline[x];
int r = p_Calculate((color>>16) & 0xFF, trackBarRedValue);
int g = p_Calculate((color>>8) & 0xFF, trackBarGreenValue);
int b = p_Calculate(color & 0xFF, trackBarBlueValue);
color = (0xFF<<24) | (r <<16) | (g<<8) | b;
destScanline[x] = color;
}
sourceScanlineBytes += sourceData.Stride;
destScanlineBytes += destData.Stride;
}
}
},
() =>
{
if (sourceData != null)
originalBitmap.UnlockBits(sourceData);
if (destData != null)
bitmap.UnlockBits(destData);
}
);
break;
}
DateTime end = DateTime.Now;
Text = "Generated image #" + fGenerationCount + " - Time:" + (end-begin);
}
// Here we write the bitmap to the form and clear the remaining area.
e.Graphics.DrawImage(bitmap, 0, 0);
e.Graphics.FillRectangle(Brushes.Black, width, 0, Width, Height);
e.Graphics.FillRectangle(Brushes.Black, 0, height, Width, Height);
}
private int p_Calculate(int colorValue, int modifier)
{
int result = colorValue + modifier;
if (result < 0)
return 0;
if (result > 255)
return 255;
return result;
}
private void trackBarRed_ValueChanged(object sender, EventArgs e)
{
numericUpDownRed.ValueChanged -= numericUpDownRed_ValueChanged;
numericUpDownRed.Value = trackBarRed.Value;
numericUpDownRed.ValueChanged += numericUpDownRed_ValueChanged;
fGenerateNew = true;
Invalidate();
}
private void trackBarGreen_Scroll(object sender, EventArgs e)
{
numericUpDownGreen.ValueChanged -= numericUpDownGreen_ValueChanged;
numericUpDownGreen.Value = trackBarGreen.Value;
numericUpDownGreen.ValueChanged += numericUpDownGreen_ValueChanged;
fGenerateNew = true;
Invalidate();
}
private void trackBarBlue_Scroll(object sender, EventArgs e)
{
numericUpDownBlue.ValueChanged -= numericUpDownBlue_ValueChanged;
numericUpDownBlue.Value = trackBarBlue.Value;
numericUpDownBlue.ValueChanged += numericUpDownBlue_ValueChanged;
fGenerateNew = true;
Invalidate();
}
private void buttonSave_Click(object sender, EventArgs e)
{
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
fBitmap.AsSystemBitmap.Save(saveFileDialog.FileName);
}
catch(Exception exception)
{
MessageBox.Show(exception.Message, exception.GetType().FullName);
}
}
}
private void numericUpDownRed_ValueChanged(object sender, EventArgs e)
{
trackBarRed.Value = (int)numericUpDownRed.Value;
}
private void numericUpDownGreen_ValueChanged(object sender, EventArgs e)
{
trackBarGreen.Value = (int)numericUpDownGreen.Value;
}
private void numericUpDownBlue_ValueChanged(object sender, EventArgs e)
{
trackBarBlue.Value = (int)numericUpDownBlue.Value;
}
}
}