using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Drawing.Imaging;
namespace OldStarsFinder
{
public partial class Form1 : Form
{
//The number of processors or cores available in the computer for this application
private int priProcessorCount = Environment.ProcessorCount;
//The bitmaps list
private List<Bitmap> prloBitmapList;
//The long list with the old stars count
private List<long> prliOldStarsCount;
//The threads list
private List<Thread> prloThreadList;
//The original huge infrared bitmap portrait
Bitmap proOriginalBitmap;
public Form1()
{
InitializeComponent();
}
public bool IsOldStar(Color poPixelColor)
{
//Hue between 150 and 258
//Saturation more than 0.10
//Brightness more than 0.90
return ((poPixelColor.GetHue() >= 150 && (poPixelColor.GetHue() <= 258)) &&
(poPixelColor.GetSaturation() >= 0.10) &&
(poPixelColor.GetBrightness() >= 0.90));
}
private Bitmap CropBitmap(Bitmap proBitmap, Rectangle proRectangle)
{
//Create a new bitmap copying the portion of the original defined by proRectangle and keeping the PixelFormat
var loCroppedBitmap = proBitmap.Clone(proRectangle, proBitmap.PixelFormat);
//Return the cropped bitmap
return loCroppedBitmap;
}
private void ThreadOldStarsFinder(object poThreadParameter)
{
//Retrieve the thread number reeived in object poThreadParameter
int liThreadNumber = (int) poThreadParameter;
//The pixel matrix (bitmap) row number (Y)
int liRow;
//The pixel matrix (bitmap col number (X)
int liCol;
//The pixel color
Color loPixelColor;
//Get my bitmap part from the bitmap list
Bitmap loBitmap = prloBitmapList[liThreadNumber];
//Reset my old stars counter
prliOldStarsCount[liThreadNumber] = 0;
//Iterate through each pixel matrix (bitmap) row
for (liRow = 0; liRow < loBitmap.Height; liRow++)
{
//Iterate through each pixel matrix (bitmap) cols
for(liCol = 0; liCol < loBitmap.Width; liCol++)
{
//Get the pixel color for liCol and liRow
loPixelColor = loBitmap.GetPixel(liCol, liRow);
//Get the pixel color for liCol and liRow
if (IsOldStar(loPixelColor))
{
//The color range correspons to an old star
//Change its color to a pure blue
loBitmap.SetPixel(liCol, liRow, Color.Blue);
//Increase the old stars counter
prliOldStarsCount[liThreadNumber]++;
}
else
{
loBitmap.SetPixel(liCol, liRow, Color.FromArgb(128, loPixelColor));
}
}
}
//Simulate heavy processing
Random rnd = new Random();
Thread.Sleep(rnd.Next(2000, 2500));
}
private void WaitForThreadsToDie()
{
//A bool flag
bool lbContinue = true;
int liDeadThreads = 0;
int liThreadNumber;
while (lbContinue)
{
for(liThreadNumber = 0; liThreadNumber < priProcessorCount; liThreadNumber++)
{
if (prloThreadList[liThreadNumber].IsAlive)
{
//One of the threads is still alive
//exit the for loop and sleep 100 milliseconds
break;
}
else
{
//Increase the dead threads count
liDeadThreads++;
progressBar1.Value = (int) ((liDeadThreads * 1.0 / priProcessorCount * 1.0) * 100.0);
}
}
if (liDeadThreads == priProcessorCount)
{
//All the threads are dead, exit the while loop
break;
}
Thread.Sleep(100);
liDeadThreads = 0;
}
}
private void ShowBitmapWithOldStars()
{
int liThreadNumber;
//Each bitmap portion
Bitmap loBitmap;
//The starting row in each iteration
int liStartRow = 0;
//Calculate each bitmap's height
int liEachBitmapHeight = ((int) (proOriginalBitmap.Height / priProcessorCount)) + 1;
//Create a new bitmap with the whole width and height
loBitmap = new Bitmap(proOriginalBitmap.Width, proOriginalBitmap.Height);
Graphics g = Graphics.FromImage((Image) loBitmap);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
for (liThreadNumber = 0; liThreadNumber < priProcessorCount; liThreadNumber++)
{
//Draw each portion in its corresponding absolute starting row
g.DrawImage(prloBitmapList[liThreadNumber], 0, liStartRow);
//Increase the starting row
liStartRow += liEachBitmapHeight;
}
//Show the bitmap in the PictureBox picStarsBitmap
picStarsBitmap.Image = loBitmap;
g.Dispose();
}
private void butFindOldStars_Click(object sender, EventArgs e)
{
progressBar1.Visible = true;
proOriginalBitmap = new Bitmap(pictureBox1.Image);
//Thread number
int liThreadNumber;
//Create the thread list, the long list and the bitmap list
prloThreadList = new List<Thread>(priProcessorCount);
prliOldStarsCount = new List<long>(priProcessorCount);
prloBitmapList = new List<Bitmap>(priProcessorCount);
int liStartRow = 0;
int liEachBitmapHeight = ((int) (proOriginalBitmap.Height / priProcessorCount)) + 1;
int liHeightToAdd = proOriginalBitmap.Height;
Bitmap loBitmap;
//Initialize the threads
for (liThreadNumber = 0; liThreadNumber < priProcessorCount; liThreadNumber++)
{
//Just to occupy the number
prliOldStarsCount.Add(0);
if (liEachBitmapHeight > liHeightToAdd)
{
//The last bitmap height perhaps is less than the other bitmap height
liEachBitmapHeight = liHeightToAdd;
}
loBitmap = CropBitmap(proOriginalBitmap, new Rectangle(0, liStartRow, proOriginalBitmap.Width, liEachBitmapHeight));
liHeightToAdd -= liEachBitmapHeight;
liStartRow += liEachBitmapHeight;
prloBitmapList.Add(loBitmap);
//Add the new thread, with a parameterized start (to allow parameters)
prloThreadList.Add(new Thread(new ParameterizedThreadStart(ThreadOldStarsFinder)));
}
//Now, start the threads
for (liThreadNumber = 0; liThreadNumber < priProcessorCount; liThreadNumber++)
{
prloThreadList[liThreadNumber].Start(liThreadNumber);
}
WaitForThreadsToDie();
ShowBitmapWithOldStars();
progressBar1.Visible = false;
}
}
}
The code is available as a Windows Forms application in a Visual 2015 Solution available for download (zip) below: Old Stars Finder (.zip) W5 image (NASA website): W5 image




Moving over to the code bit, I define the following in MainWindow (Source of the form), which is the code behind: