Skip to content
This repository was archived by the owner on Sep 21, 2023. It is now read-only.

Commit 464e9a7

Browse files
committed
Add YCbCr colorspace split
1 parent 7a317e8 commit 464e9a7

9 files changed

+420
-9
lines changed

winforms-image-processor/winforms-image-processor/CacheManager/CacheManager.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static void ResetCache(Bitmap bmp)
5454

5555
public static Bitmap GetOriginalImage() => cachedFilterStates[new List<string>()];
5656

57-
private static T DeepCopy<T>(T source)
57+
public static T DeepCopy<T>(T source)
5858
// Sources used
5959
// Deepcopy w/ stream: https://stackoverflow.com/questions/43039099/creating-a-completely-new-copy-of-bitmap-from-a-bitmap-in-c-sharp/43042865#43042865
6060
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace winforms_image_processor
8+
{
9+
static class ColorspaceTools
10+
{
11+
public static void RGBtoYBR(int R, int G, int B, out int Y, out int Cb, out int Cr)
12+
{
13+
Y = (int)((0.299 * R) + (0.587 * G) + (0.114 * B));
14+
Cb = (int)(128 - (0.168736 * R) + (0.331264 * G) + (0.5 * B));
15+
Cr = (int)(128 + (0.5 * R) + (0.418688 * G) + (0.081312 * B));
16+
}
17+
}
18+
}

winforms-image-processor/winforms-image-processor/Filters/FilterManager.cs

+52
Original file line numberDiff line numberDiff line change
@@ -271,5 +271,57 @@ static public byte[] OctreeQuantization(byte[] buffer)
271271
return result;
272272
}
273273

274+
///////////////////////////////
275+
// YCbCr Colorspace Filters //
276+
/////////////////////////////
277+
278+
static public byte[] YGrayscale(byte[] buffer)
279+
{
280+
byte[] result = new byte[buffer.Length];
281+
282+
for (int i = 0; i < buffer.Length; i += 4)
283+
{
284+
ColorspaceTools.RGBtoYBR(buffer[i + 2], buffer[i + 1], buffer[i], out int Y, out _, out _);
285+
286+
result[i + 0] = result[i + 1] = result[i + 2] = (byte)Y;
287+
result[i + 3] = 255;
288+
}
289+
290+
return result;
291+
}
292+
293+
static public byte[] CbInterpolate(byte[] buffer)
294+
{
295+
byte[] result = new byte[buffer.Length];
296+
297+
for (int i = 0; i < buffer.Length; i += 4)
298+
{
299+
ColorspaceTools.RGBtoYBR(buffer[i + 2], buffer[i + 1], buffer[i], out int Y, out int Cb, out int Cr);
300+
301+
result[i] = (byte)((1 - Cb) * 0 + Cb * 255);
302+
result[i + 1] = (byte) ((1 - Cb) * 255 + Cb * 0);
303+
result[i + 2] = (byte) ((1 - Cb) * 127 + Cb * 127);
304+
result[i + 3] = 255;
305+
}
306+
307+
return result;
308+
}
309+
310+
static public byte[] CrInterpolate(byte[] buffer)
311+
{
312+
byte[] result = new byte[buffer.Length];
313+
314+
for (int i = 0; i < buffer.Length; i += 4)
315+
{
316+
ColorspaceTools.RGBtoYBR(buffer[i + 2], buffer[i + 1], buffer[i], out int Y, out int Cb, out int Cr);
317+
318+
result[i] = (byte)((1 - Cr) * 127 + Cr * 127);
319+
result[i + 1] = (byte)((1 - Cr) * 255 + Cr * 0);
320+
result[i + 2] = (byte)((1 - Cr) * 0 + Cr * 255);
321+
result[i + 3] = 255;
322+
}
323+
324+
return result;
325+
}
274326
}
275327
}

winforms-image-processor/winforms-image-processor/Form/ImageProcessorForm.Designer.cs

+19-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

winforms-image-processor/winforms-image-processor/Form/ImageProcessorForm.cs

+12
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ private void StateChange(object sender, EventArgs e)
6666
UpdateCacheIfEmpty();
6767

6868
FltPictureBox.Image = CacheManager.GetBitmapForFilterState();
69+
70+
yBRColorspaceDisplay.updateImages((Bitmap)FltPictureBox.Image);
6971
}
7072

7173
public void UpdateCacheIfEmpty()
@@ -105,6 +107,7 @@ private void OpenImageFileMenu_Click(object sender, EventArgs e)
105107
filtersToolStripMenuItem.Enabled = true;
106108
SaveImageFileMenu.Enabled = true;
107109
customKernelToolStripMenuItem.Enabled = true;
110+
yBRSplitToolStripMenuItem.Enabled = true;
108111

109112
if (CacheManager.cachedFilterStates != null)
110113
{
@@ -228,5 +231,14 @@ private void UncheckToolsRecursion(ToolStripMenuItem tsmi)
228231
UncheckToolsRecursion(innerTsmi);
229232
}
230233
}
234+
235+
public YBRColorspaceDisplay yBRColorspaceDisplay;
236+
237+
private void yBRSplitToolStripMenuItem_Click(object sender, EventArgs e)
238+
{
239+
yBRColorspaceDisplay = new YBRColorspaceDisplay(this, (Bitmap)FltPictureBox.Image);
240+
241+
yBRColorspaceDisplay.Show();
242+
}
231243
}
232244
}

winforms-image-processor/winforms-image-processor/Form/YBRColorspaceDisplay.Designer.cs

+112
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.Data;
5+
using System.Drawing;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using System.Windows.Forms;
10+
11+
namespace winforms_image_processor
12+
{
13+
public partial class YBRColorspaceDisplay : Form
14+
{
15+
private ImageProcessorForm imageProcessorForm;
16+
private Bitmap currentFilterImage;
17+
18+
public YBRColorspaceDisplay(Form callerForm, Bitmap currentFltImage)
19+
{
20+
currentFilterImage = CacheManager.DeepCopy(currentFltImage);
21+
imageProcessorForm = callerForm as ImageProcessorForm;
22+
23+
InitializeComponent();
24+
25+
Height = callerForm.Height;
26+
27+
setUpImages();
28+
}
29+
30+
public void setUpImages()
31+
{
32+
setUpYImage();
33+
setUpCbImage();
34+
setUpCrImage();
35+
}
36+
37+
public void updateImages(Bitmap currFltImage)
38+
{
39+
currentFilterImage = currFltImage;
40+
41+
setUpImages();
42+
}
43+
44+
void setUpYImage()
45+
{
46+
Bitmap YImageBmp = CacheManager.DeepCopy<Bitmap>(currentFilterImage);
47+
48+
YImageBmp = YImageBmp.ApplyFilter(FilterManager.YGrayscale);
49+
50+
YImage.Image = YImageBmp;
51+
}
52+
53+
void setUpCbImage()
54+
{
55+
Bitmap CbImageBmp = CacheManager.DeepCopy<Bitmap>(currentFilterImage);
56+
57+
CbImageBmp = CbImageBmp.ApplyFilter(FilterManager.CbInterpolate);
58+
59+
CbImage.Image = CbImageBmp;
60+
}
61+
62+
void setUpCrImage()
63+
{
64+
Bitmap CrImageBmp = CacheManager.DeepCopy<Bitmap>(currentFilterImage);
65+
66+
CrImageBmp = CrImageBmp.ApplyFilter(FilterManager.CrInterpolate);
67+
68+
CrImage.Image = CrImageBmp;
69+
}
70+
71+
private void YBRColorspaceDisplay_FormClosed(object sender, FormClosedEventArgs e)
72+
{
73+
imageProcessorForm.yBRColorspaceDisplay = null;
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)